From 0ebd762347e9170540f2ad21870e8cd692346637 Mon Sep 17 00:00:00 2001 From: cl Date: Mon, 14 Jun 2004 13:55:52 +0000 Subject: [PATCH] cleanup low-level bit mangling code --- sys/arch/xen/i386/hypervisor_machdep.c | 39 ++-- sys/arch/xen/include/hypervisor.h | 11 +- sys/arch/xen/include/xen.h | 238 +++++++++---------------- 3 files changed, 114 insertions(+), 174 deletions(-) diff --git a/sys/arch/xen/i386/hypervisor_machdep.c b/sys/arch/xen/i386/hypervisor_machdep.c index b6658fe59331..8c1ddd62816b 100644 --- a/sys/arch/xen/i386/hypervisor_machdep.c +++ b/sys/arch/xen/i386/hypervisor_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: hypervisor_machdep.c,v 1.2 2004/04/24 17:41:49 cl Exp $ */ +/* $NetBSD: hypervisor_machdep.c,v 1.3 2004/06/14 13:55:52 cl Exp $ */ /* * @@ -59,7 +59,7 @@ #include -__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.2 2004/04/24 17:41:49 cl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.3 2004/06/14 13:55:52 cl Exp $"); #include #include @@ -69,7 +69,6 @@ __KERNEL_RCSID(0, "$NetBSD: hypervisor_machdep.c,v 1.2 2004/04/24 17:41:49 cl Ex #include /* static */ unsigned long event_mask = 0; -static unsigned long ev_err_count; int stipending(void); int @@ -96,7 +95,7 @@ stipending() */ __cli(); - events = xchg(&HYPERVISOR_shared_info->events, 0); + events = x86_atomic_xchg(&HYPERVISOR_shared_info->events, 0); events &= event_mask; while (events) { @@ -140,11 +139,11 @@ void do_hypervisor_callback(struct trapframe *regs) do { /* Specialised local_irq_save(). */ - flags = test_and_clear_bit(EVENTS_MASTER_ENABLE_BIT, - &shared->events_mask); - barrier(); + flags = x86_atomic_test_and_clear_bit(&shared->events_mask, + EVENTS_MASTER_ENABLE_BIT); + __insn_barrier(); - events = xchg(&shared->events, 0); + events = x86_atomic_xchg(&shared->events, 0); events &= event_mask; /* 'events' now contains some pending events to handle. */ @@ -165,8 +164,9 @@ void do_hypervisor_callback(struct trapframe *regs) /* Specialised local_irq_restore(). */ if (flags) - set_bit(EVENTS_MASTER_ENABLE_BIT, &shared->events_mask); - barrier(); + x86_atomic_set_bit(&shared->events_mask, + EVENTS_MASTER_ENABLE_BIT); + __insn_barrier(); } while ( shared->events ); @@ -180,24 +180,25 @@ void do_hypervisor_callback(struct trapframe *regs) void hypervisor_enable_event(unsigned int ev) { - set_bit(ev, &event_mask); - set_bit(ev, &HYPERVISOR_shared_info->events_mask); + x86_atomic_set_bit(&event_mask, ev); + x86_atomic_set_bit(&HYPERVISOR_shared_info->events_mask, ev); #if 0 - if ( test_bit(EVENTS_MASTER_ENABLE_BIT, - &HYPERVISOR_shared_info->events_mask) ) + if (x86_atomic_test_bit(&HYPERVISOR_shared_info->events_mask, + EVENTS_MASTER_ENABLE_BIT)) do_hypervisor_callback(NULL); #endif } void hypervisor_disable_event(unsigned int ev) { - clear_bit(ev, &event_mask); - clear_bit(ev, &HYPERVISOR_shared_info->events_mask); + + x86_atomic_clear_bit(&event_mask, ev); + x86_atomic_clear_bit(&HYPERVISOR_shared_info->events_mask, ev); } void hypervisor_acknowledge_event(unsigned int ev) { - if ( !(event_mask & (1<events_mask); + + /* XXX add event counter for stray events: !(event_mask & (1<events_mask, ev); } diff --git a/sys/arch/xen/include/hypervisor.h b/sys/arch/xen/include/hypervisor.h index 4e85daec43c7..d610b87ccfa7 100644 --- a/sys/arch/xen/include/hypervisor.h +++ b/sys/arch/xen/include/hypervisor.h @@ -1,4 +1,4 @@ -/* $NetBSD: hypervisor.h,v 1.7 2004/04/26 22:05:05 cl Exp $ */ +/* $NetBSD: hypervisor.h,v 1.8 2004/06/14 13:55:52 cl Exp $ */ /* * @@ -43,12 +43,21 @@ struct xen_npx_attach_args { }; +#define u16 uint16_t +#define u32 uint32_t +#define u64 uint64_t + /* include the hypervisor interface */ #include #include #include #include #include +#include + +#undef u16 +#undef u32 +#undef u64 /* diff --git a/sys/arch/xen/include/xen.h b/sys/arch/xen/include/xen.h index e5d81c831f5b..785b4f654b34 100644 --- a/sys/arch/xen/include/xen.h +++ b/sys/arch/xen/include/xen.h @@ -1,4 +1,4 @@ -/* $NetBSD: xen.h,v 1.7 2004/05/07 15:51:04 cl Exp $ */ +/* $NetBSD: xen.h,v 1.8 2004/06/14 13:55:52 cl Exp $ */ /* * @@ -54,10 +54,6 @@ void xenmachmem_init(void); void xenprivcmd_init(void); void xenvfr_init(void); -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - #ifdef XENDEBUG void printk(const char *, ...); void vprintk(const char *, va_list); @@ -110,8 +106,6 @@ void vprintk(const char *, va_list); /* Everything below this point is not included by assembler (.S) files. */ #ifndef _LOCORE -#include - /* some function prototypes */ void trap_init(void); @@ -122,185 +116,121 @@ void trap_init(void); * the enable bit is set, there may be pending events to be handled. * We may therefore call into do_hypervisor_callback() directly. */ -#define unlikely(x) __builtin_expect((x),0) -#define __save_flags(x) \ -do { \ - (x) = test_bit(EVENTS_MASTER_ENABLE_BIT, \ - &HYPERVISOR_shared_info->events_mask); \ - barrier(); \ + +#define __save_flags(x) \ +do { \ + (x) = x86_atomic_test_bit(&HYPERVISOR_shared_info->events_mask, \ + EVENTS_MASTER_ENABLE_BIT); \ + __insn_barrier(); \ } while (0) -#define __restore_flags(x) \ -do { \ - shared_info_t *_shared = HYPERVISOR_shared_info; \ - if (x) set_bit(EVENTS_MASTER_ENABLE_BIT, &_shared->events_mask); \ - barrier(); \ +#define __restore_flags(x) \ +do { \ + shared_info_t *_shared = HYPERVISOR_shared_info; \ + if (x) x86_atomic_set_bit(&_shared->events_mask, \ + EVENTS_MASTER_ENABLE_BIT); \ + __insn_barrier(); \ } while (0) -/* if ( unlikely(_shared->events) && (x) ) do_hypervisor_callback(NULL); \ */ +/* if (__predict_false(_shared->events) && (x)) do_hypervisor_callback(NULL); \ */ -#define __cli() \ -do { \ - clear_bit(EVENTS_MASTER_ENABLE_BIT, &HYPERVISOR_shared_info->events_mask);\ - barrier(); \ +#define __cli() \ +do { \ + x86_atomic_clear_bit(&HYPERVISOR_shared_info->events_mask, \ + EVENTS_MASTER_ENABLE_BIT); \ + __insn_barrier(); \ } while (0) -#define __sti() \ -do { \ - shared_info_t *_shared = HYPERVISOR_shared_info; \ - set_bit(EVENTS_MASTER_ENABLE_BIT, &_shared->events_mask); \ - barrier(); \ +#define __sti() \ +do { \ + shared_info_t *_shared = HYPERVISOR_shared_info; \ + x86_atomic_set_bit(&_shared->events_mask, \ + EVENTS_MASTER_ENABLE_BIT); \ + __insn_barrier(); \ } while (0) -/* if ( unlikely(_shared->events) ) do_hypervisor_callback(NULL); \ */ -#define cli() __cli() -#define sti() __sti() -#define save_flags(x) __save_flags(x) -#define restore_flags(x) __restore_flags(x) -#define save_and_cli(x) __save_and_cli(x) -#define save_and_sti(x) __save_and_sti(x) +/* if (__predict_false(_shared->events)) do_hypervisor_callback(NULL); \ */ +#define cli() __cli() +#define sti() __sti() +#define save_flags(x) __save_flags(x) +#define restore_flags(x) __restore_flags(x) +#define save_and_cli(x) __save_and_cli(x) +#define save_and_sti(x) __save_and_sti(x) - -/* This is a barrier for the compiler only, NOT the processor! */ -#define barrier() __asm__ __volatile__("": : :"memory") - +#ifdef MULTIPROCESSOR +#define __LOCK_PREFIX "lock; " +#else #define __LOCK_PREFIX "" -#define __LOCK "" -#define __ADDR (*(volatile long *) addr) -/* - * Make sure gcc doesn't try to be clever and move things around - * on us. We need to use _exactly_ the address the user gave us, - * not some alias that contains the same information. - */ -typedef struct { volatile int counter; } atomic_t; +#endif - -#define xchg(ptr,v) \ - ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) -struct __xchg_dummy { unsigned long a[100]; }; -#define __xg(x) ((struct __xchg_dummy *)(x)) -static inline unsigned long __xchg(unsigned long x, volatile void * ptr, - int size) +static __inline__ unsigned long +x86_atomic_xchg(unsigned long *ptr, unsigned long val) { - switch (size) { - case 1: - __asm__ __volatile__("xchgb %b0,%1" - :"=q" (x) - :"m" (*__xg(ptr)), "0" (x) - :"memory"); - break; - case 2: - __asm__ __volatile__("xchgw %w0,%1" - :"=r" (x) - :"m" (*__xg(ptr)), "0" (x) - :"memory"); - break; - case 4: - __asm__ __volatile__("xchgl %0,%1" - :"=r" (x) - :"m" (*__xg(ptr)), "0" (x) - :"memory"); - break; - } - return x; + unsigned long result; + + __asm __volatile("xchgl %0,%1" + :"=r" (result) + :"m" (*ptr), "0" (val) + :"memory"); + + return result; } -/** - * test_and_clear_bit - Clear a bit and return its old value - * @nr: Bit to set - * @addr: Address to count from - * - * This operation is atomic and cannot be reordered. - * It also implies a memory barrier. - */ -static __inline__ int test_and_clear_bit(int nr, volatile void * addr) +static __inline__ int +x86_atomic_test_and_clear_bit(volatile void *ptr, int bitno) { - int oldbit; + int result; - __asm__ __volatile__( __LOCK_PREFIX - "btrl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit),"=m" (__ADDR) - :"Ir" (nr) : "memory"); - return oldbit; + __asm __volatile(__LOCK_PREFIX + "btrl %2,%1 ;" + "sbbl %0,%0" + :"=r" (result), "=m" (*(volatile uint32_t *)(ptr)) + :"Ir" (bitno) : "memory"); + return result; } -static __inline__ int constant_test_bit(int nr, const volatile void * addr) +static __inline int +x86_constant_test_bit(const volatile void *ptr, int bitno) { - return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; + return ((1UL << (bitno & 31)) & + (((const volatile uint32_t *) ptr)[bitno >> 5])) != 0; } -static __inline__ int variable_test_bit(int nr, volatile void * addr) +static __inline int +x86_variable_test_bit(const volatile void *ptr, int bitno) { - int oldbit; + int result; - __asm__ __volatile__( - "btl %2,%1\n\tsbbl %0,%0" - :"=r" (oldbit) - :"m" (__ADDR),"Ir" (nr)); - return oldbit; + __asm __volatile( + "btl %2,%1 ;" + "sbbl %0,%0" + :"=r" (result) + :"m" (*(volatile uint32_t *)(ptr)), "Ir" (bitno)); + return result; } -#define test_bit(nr,addr) \ -(__builtin_constant_p(nr) ? \ - constant_test_bit((nr),(addr)) : \ - variable_test_bit((nr),(addr))) +#define x86_atomic_test_bit(ptr, bitno) \ + (__builtin_constant_p(bitno) ? \ + x86_constant_test_bit((ptr),(bitno)) : \ + variable_test_bit((ptr),(bitno))) - -/** - * set_bit - Atomically set a bit in memory - * @nr: the bit to set - * @addr: the address to start counting from - * - * This function is atomic and may not be reordered. See __set_bit() - * if you do not require the atomic guarantees. - * Note that @nr may be almost arbitrarily large; this function is not - * restricted to acting on a single-word quantity. - */ -static __inline__ void set_bit(int nr, volatile void * addr) +static __inline void +x86_atomic_set_bit(volatile void *ptr, int bitno) { - __asm__ __volatile__( __LOCK_PREFIX - "btsl %1,%0" - :"=m" (__ADDR) - :"Ir" (nr)); + __asm __volatile(__LOCK_PREFIX + "btsl %1,%0" + :"=m" (*(volatile uint32_t *)(ptr)) + :"Ir" (bitno)); } -/** - * clear_bit - Clears a bit in memory - * @nr: Bit to clear - * @addr: Address to start counting from - * - * clear_bit() is atomic and may not be reordered. However, it does - * not contain a memory barrier, so if it is used for locking purposes, - * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() - * in order to ensure changes are visible on other processors. - */ -static __inline__ void clear_bit(int nr, volatile void * addr) +static __inline void +x86_atomic_clear_bit(volatile void *ptr, int bitno) { - __asm__ __volatile__( __LOCK_PREFIX - "btrl %1,%0" - :"=m" (__ADDR) - :"Ir" (nr)); + __asm __volatile(__LOCK_PREFIX + "btrl %1,%0" + :"=m" (*(volatile uint32_t *)(ptr)) + :"Ir" (bitno)); } -/** - * atomic_inc - increment atomic variable - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1. Note that the guaranteed - * useful range of an atomic_t is only 24 bits. - */ -static __inline__ void atomic_inc(atomic_t *v) -{ - __asm__ __volatile__( - __LOCK "incl %0" - :"=m" (v->counter) - :"m" (v->counter)); -} - - -#define rdtscll(val) \ - __asm__ __volatile__("rdtsc" : "=A" (val)) - - #endif /* !__ASSEMBLY__ */ #endif /* _OS_H_ */