1 /****************************************************************************** 2 * os.h 3 * 4 * random collection of macros and definition 5 * 6 * $FreeBSD$ 7 */ 8 9 #ifndef _XEN_OS_H_ 10 #define _XEN_OS_H_ 11 12 #ifdef PAE 13 #define CONFIG_X86_PAE 14 #endif 15 16 #ifdef LOCORE 17 #define __ASSEMBLY__ 18 #endif 19 20 #if !defined(__XEN_INTERFACE_VERSION__) 21 #define __XEN_INTERFACE_VERSION__ 0x00030208 22 #endif 23 24 #define GRANT_REF_INVALID 0xffffffff 25 26 #include <xen/interface/xen.h> 27 28 /* Everything below this point is not included by assembler (.S) files. */ 29 #ifndef __ASSEMBLY__ 30 31 /* Force a proper event-channel callback from Xen. */ 32 void force_evtchn_callback(void); 33 34 extern int gdtset; 35 36 extern shared_info_t *HYPERVISOR_shared_info; 37 38 /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ 39 static inline void rep_nop(void) 40 { 41 __asm__ __volatile__ ( "rep;nop" : : : "memory" ); 42 } 43 #define cpu_relax() rep_nop() 44 45 /* crude memory allocator for memory allocation early in 46 * boot 47 */ 48 void *bootmem_alloc(unsigned int size); 49 void bootmem_free(void *ptr, unsigned int size); 50 51 void printk(const char *fmt, ...); 52 53 /* some function prototypes */ 54 void trap_init(void); 55 56 #define likely(x) __builtin_expect((x),1) 57 #define unlikely(x) __builtin_expect((x),0) 58 59 #ifndef XENHVM 60 61 /* 62 * STI/CLI equivalents. These basically set and clear the virtual 63 * event_enable flag in the shared_info structure. Note that when 64 * the enable bit is set, there may be pending events to be handled. 65 * We may therefore call into do_hypervisor_callback() directly. 66 */ 67 68 #define __cli() \ 69 do { \ 70 vcpu_info_t *_vcpu; \ 71 _vcpu = &HYPERVISOR_shared_info->vcpu_info[PCPU_GET(cpuid)]; \ 72 _vcpu->evtchn_upcall_mask = 1; \ 73 barrier(); \ 74 } while (0) 75 76 #define __sti() \ 77 do { \ 78 vcpu_info_t *_vcpu; \ 79 barrier(); \ 80 _vcpu = &HYPERVISOR_shared_info->vcpu_info[PCPU_GET(cpuid)]; \ 81 _vcpu->evtchn_upcall_mask = 0; \ 82 barrier(); /* unmask then check (avoid races) */ \ 83 if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ 84 force_evtchn_callback(); \ 85 } while (0) 86 87 #define __restore_flags(x) \ 88 do { \ 89 vcpu_info_t *_vcpu; \ 90 barrier(); \ 91 _vcpu = &HYPERVISOR_shared_info->vcpu_info[PCPU_GET(cpuid)]; \ 92 if ((_vcpu->evtchn_upcall_mask = (x)) == 0) { \ 93 barrier(); /* unmask then check (avoid races) */ \ 94 if ( unlikely(_vcpu->evtchn_upcall_pending) ) \ 95 force_evtchn_callback(); \ 96 } \ 97 } while (0) 98 99 /* 100 * Add critical_{enter, exit}? 101 * 102 */ 103 #define __save_and_cli(x) \ 104 do { \ 105 vcpu_info_t *_vcpu; \ 106 _vcpu = &HYPERVISOR_shared_info->vcpu_info[PCPU_GET(cpuid)]; \ 107 (x) = _vcpu->evtchn_upcall_mask; \ 108 _vcpu->evtchn_upcall_mask = 1; \ 109 barrier(); \ 110 } while (0) 111 112 113 #define cli() __cli() 114 #define sti() __sti() 115 #define save_flags(x) __save_flags(x) 116 #define restore_flags(x) __restore_flags(x) 117 #define save_and_cli(x) __save_and_cli(x) 118 119 #define local_irq_save(x) __save_and_cli(x) 120 #define local_irq_restore(x) __restore_flags(x) 121 #define local_irq_disable() __cli() 122 #define local_irq_enable() __sti() 123 124 #define mtx_lock_irqsave(lock, x) {local_irq_save((x)); mtx_lock_spin((lock));} 125 #define mtx_unlock_irqrestore(lock, x) {mtx_unlock_spin((lock)); local_irq_restore((x)); } 126 #define spin_lock_irqsave mtx_lock_irqsave 127 #define spin_unlock_irqrestore mtx_unlock_irqrestore 128 129 #else 130 #endif 131 132 #ifndef xen_mb 133 #define xen_mb() mb() 134 #endif 135 #ifndef xen_rmb 136 #define xen_rmb() rmb() 137 #endif 138 #ifndef xen_wmb 139 #define xen_wmb() wmb() 140 #endif 141 #ifdef SMP 142 #define smp_mb() mb() 143 #define smp_rmb() rmb() 144 #define smp_wmb() wmb() 145 #define smp_read_barrier_depends() read_barrier_depends() 146 #define set_mb(var, value) do { xchg(&var, value); } while (0) 147 #else 148 #define smp_mb() barrier() 149 #define smp_rmb() barrier() 150 #define smp_wmb() barrier() 151 #define smp_read_barrier_depends() do { } while(0) 152 #define set_mb(var, value) do { var = value; barrier(); } while (0) 153 #endif 154 155 156 /* This is a barrier for the compiler only, NOT the processor! */ 157 #define barrier() __asm__ __volatile__("": : :"memory") 158 159 #define LOCK_PREFIX "" 160 #define LOCK "" 161 #define ADDR (*(volatile long *) addr) 162 /* 163 * Make sure gcc doesn't try to be clever and move things around 164 * on us. We need to use _exactly_ the address the user gave us, 165 * not some alias that contains the same information. 166 */ 167 typedef struct { volatile int counter; } atomic_t; 168 169 170 171 #define xen_xchg(ptr,v) \ 172 ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) 173 struct __xchg_dummy { unsigned long a[100]; }; 174 #define __xg(x) ((volatile struct __xchg_dummy *)(x)) 175 static __inline unsigned long __xchg(unsigned long x, volatile void * ptr, 176 int size) 177 { 178 switch (size) { 179 case 1: 180 __asm__ __volatile__("xchgb %b0,%1" 181 :"=q" (x) 182 :"m" (*__xg(ptr)), "0" (x) 183 :"memory"); 184 break; 185 case 2: 186 __asm__ __volatile__("xchgw %w0,%1" 187 :"=r" (x) 188 :"m" (*__xg(ptr)), "0" (x) 189 :"memory"); 190 break; 191 case 4: 192 __asm__ __volatile__("xchgl %0,%1" 193 :"=r" (x) 194 :"m" (*__xg(ptr)), "0" (x) 195 :"memory"); 196 break; 197 } 198 return x; 199 } 200 201 /** 202 * test_and_clear_bit - Clear a bit and return its old value 203 * @nr: Bit to set 204 * @addr: Address to count from 205 * 206 * This operation is atomic and cannot be reordered. 207 * It also implies a memory barrier. 208 */ 209 static __inline int test_and_clear_bit(int nr, volatile void * addr) 210 { 211 int oldbit; 212 213 __asm__ __volatile__( LOCK_PREFIX 214 "btrl %2,%1\n\tsbbl %0,%0" 215 :"=r" (oldbit),"=m" (ADDR) 216 :"Ir" (nr) : "memory"); 217 return oldbit; 218 } 219 220 static __inline int constant_test_bit(int nr, const volatile void * addr) 221 { 222 return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; 223 } 224 225 static __inline int variable_test_bit(int nr, volatile void * addr) 226 { 227 int oldbit; 228 229 __asm__ __volatile__( 230 "btl %2,%1\n\tsbbl %0,%0" 231 :"=r" (oldbit) 232 :"m" (ADDR),"Ir" (nr)); 233 return oldbit; 234 } 235 236 #define test_bit(nr,addr) \ 237 (__builtin_constant_p(nr) ? \ 238 constant_test_bit((nr),(addr)) : \ 239 variable_test_bit((nr),(addr))) 240 241 242 /** 243 * set_bit - Atomically set a bit in memory 244 * @nr: the bit to set 245 * @addr: the address to start counting from 246 * 247 * This function is atomic and may not be reordered. See __set_bit() 248 * if you do not require the atomic guarantees. 249 * Note that @nr may be almost arbitrarily large; this function is not 250 * restricted to acting on a single-word quantity. 251 */ 252 static __inline__ void set_bit(int nr, volatile void * addr) 253 { 254 __asm__ __volatile__( LOCK_PREFIX 255 "btsl %1,%0" 256 :"=m" (ADDR) 257 :"Ir" (nr)); 258 } 259 260 /** 261 * clear_bit - Clears a bit in memory 262 * @nr: Bit to clear 263 * @addr: Address to start counting from 264 * 265 * clear_bit() is atomic and may not be reordered. However, it does 266 * not contain a memory barrier, so if it is used for locking purposes, 267 * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() 268 * in order to ensure changes are visible on other processors. 269 */ 270 static __inline__ void clear_bit(int nr, volatile void * addr) 271 { 272 __asm__ __volatile__( LOCK_PREFIX 273 "btrl %1,%0" 274 :"=m" (ADDR) 275 :"Ir" (nr)); 276 } 277 278 /** 279 * atomic_inc - increment atomic variable 280 * @v: pointer of type atomic_t 281 * 282 * Atomically increments @v by 1. Note that the guaranteed 283 * useful range of an atomic_t is only 24 bits. 284 */ 285 static __inline__ void atomic_inc(atomic_t *v) 286 { 287 __asm__ __volatile__( 288 LOCK "incl %0" 289 :"=m" (v->counter) 290 :"m" (v->counter)); 291 } 292 293 294 #define rdtscll(val) \ 295 __asm__ __volatile__("rdtsc" : "=A" (val)) 296 297 #endif /* !__ASSEMBLY__ */ 298 299 #endif /* _OS_H_ */ 300