From patchwork Tue Aug 31 08:37:15 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Wang X-Patchwork-Id: 144721 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o7V8bLmA008952 for ; Tue, 31 Aug 2010 08:37:21 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752855Ab0HaIhT (ORCPT ); Tue, 31 Aug 2010 04:37:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:14496 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752420Ab0HaIhS (ORCPT ); Tue, 31 Aug 2010 04:37:18 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o7V8bHxX010368 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 31 Aug 2010 04:37:18 -0400 Received: from [127.0.1.1] (dhcp-65-37.nay.redhat.com [10.66.65.37]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o7V8bEpQ023516; Tue, 31 Aug 2010 04:37:15 -0400 Subject: [PATCH kvm-unit-tests v2 4/8] Introduce atomic operations To: zamsden@redhat.com, glommer@redhat.com, mtosatti@redhat.com, avi@redhat.com, kvm@vger.kernel.org From: Jason Wang Date: Tue, 31 Aug 2010 16:37:15 +0800 Message-ID: <20100831083715.10672.96696.stgit@FreeLancer> In-Reply-To: <20100831083216.10672.20413.stgit@FreeLancer> References: <20100831083216.10672.20413.stgit@FreeLancer> User-Agent: StGit/0.15 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Tue, 31 Aug 2010 08:37:22 +0000 (UTC) diff --git a/config-x86-common.mak b/config-x86-common.mak index fdb9e3e..b8ca859 100644 --- a/config-x86-common.mak +++ b/config-x86-common.mak @@ -10,6 +10,7 @@ cflatobjs += \ cflatobjs += lib/x86/fwcfg.o cflatobjs += lib/x86/apic.o +cflatobjs += lib/x86/atomic.o $(libcflat): LDFLAGS += -nostdlib $(libcflat): CFLAGS += -ffreestanding -I lib diff --git a/lib/x86/atomic.c b/lib/x86/atomic.c new file mode 100644 index 0000000..da74ff2 --- /dev/null +++ b/lib/x86/atomic.c @@ -0,0 +1,37 @@ +#include +#include "atomic.h" + +#ifdef __i386__ + +u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new) +{ + u32 low = new; + u32 high = new >> 32; + + asm volatile("lock cmpxchg8b %1\n" + : "+A" (old), + "+m" (*(volatile long long *)&v->counter) + : "b" (low), "c" (high) + : "memory" + ); + + return old; +} + +#else + +u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new) +{ + u64 ret; + u64 _old = old; + u64 _new = new; + + asm volatile("lock cmpxchgq %2,%1" + : "=a" (ret), "+m" (*(volatile long *)&v->counter) + : "r" (_new), "0" (_old) + : "memory" + ); + return ret; +} + +#endif diff --git a/lib/x86/atomic.h b/lib/x86/atomic.h new file mode 100644 index 0000000..de2f033 --- /dev/null +++ b/lib/x86/atomic.h @@ -0,0 +1,164 @@ +#ifndef __ATOMIC_H +#define __ATOMIC_H + +typedef struct { + volatile int counter; +} atomic_t; + +#ifdef __i386__ + +/** + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. + */ +static inline int atomic_read(const atomic_t *v) +{ + return v->counter; +} + +/** + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. + */ +static inline void atomic_set(atomic_t *v, int i) +{ + v->counter = i; +} + +/** + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. + */ +static inline void atomic_inc(atomic_t *v) +{ + asm volatile("lock incl %0" + : "+m" (v->counter)); +} + +/** + * atomic_dec - decrement atomic variable + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. + */ +static inline void atomic_dec(atomic_t *v) +{ + asm volatile("lock decl %0" + : "+m" (v->counter)); +} + +typedef struct { + u64 __attribute__((aligned(8))) counter; +} atomic64_t; + +#define ATOMIC64_INIT(val) { (val) } + +/** + * atomic64_read - read atomic64 variable + * @ptr: pointer to type atomic64_t + * + * Atomically reads the value of @ptr and returns it. + */ +static inline u64 atomic64_read(atomic64_t *ptr) +{ + u64 res; + + /* + * Note, we inline this atomic64_t primitive because + * it only clobbers EAX/EDX and leaves the others + * untouched. We also (somewhat subtly) rely on the + * fact that cmpxchg8b returns the current 64-bit value + * of the memory location we are touching: + */ + asm volatile("mov %%ebx, %%eax\n\t" + "mov %%ecx, %%edx\n\t" + "lock cmpxchg8b %1\n" + : "=&A" (res) + : "m" (*ptr) + ); + return res; +} + +u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new); + +#elif defined(__x86_64__) + +/** + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. + */ +static inline int atomic_read(const atomic_t *v) +{ + return v->counter; +} + +/** + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. + */ +static inline void atomic_set(atomic_t *v, int i) +{ + v->counter = i; +} + +/** + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. + */ +static inline void atomic_inc(atomic_t *v) +{ + asm volatile("lock incl %0" + : "=m" (v->counter) + : "m" (v->counter)); +} + +/** + * atomic_dec - decrement atomic variable + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. + */ +static inline void atomic_dec(atomic_t *v) +{ + asm volatile("lock decl %0" + : "=m" (v->counter) + : "m" (v->counter)); +} + +typedef struct { + long long counter; +} atomic64_t; + +#define ATOMIC64_INIT(i) { (i) } + +/** + * atomic64_read - read atomic64 variable + * @v: pointer of type atomic64_t + * + * Atomically reads the value of @v. + * Doesn't imply a read memory barrier. + */ +static inline long atomic64_read(const atomic64_t *v) +{ + return v->counter; +} + +u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new); + +#endif + +#endif