criu/arch/ppc64/include/asm/atomic.h
Laurent Dufour 303b875892 arch/ppc64: Add PowerPC 64 LE support
This patch initiates the ppc64le architecture support in CRIU.

Note that ppc64 (Big Endian) architecture is not yet supported since there
are still several issues to address with this architecture. However, in the
long term, the two architectures should be addressed using the almost the
same code, so sharing the ppc64 directory.

Major ppc64 issues:

Loader is not involved when the parasite code is loaded. So no relocation
is done for the parasite code. As a consequence r2 must be set manually
when entering the parasite code, and GOT is not filled.

Furthermore, the r2 fixup code at the services's global address which has
not been fixed by the loader should not be run. Branching at local address,
as the assembly code does is jumping over it.

On the long term, relocation should be done when loading the parasite code.

We are introducing 2 trampolines for the 2 entry points of the restorer
blob.  These entry points are dealing with r2. These ppc64 specific entry
points are overwritting the standard one in sigreturn_restore() from
cr-restore.c.  Instead of using #ifdef, we may introduce a per arch wrapper
here.

CRIU needs 2 kernel patches to be run powerpc which are not yet upstream:
 - Tracking the vDSO remapping
 - Enabling the kcmp system call on powerpc

Feature not yet supported:
- Altivec registers C/R
- VSX registers C/R
- TM support
- all lot of things I missed..

Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
2015-04-30 09:57:49 +03:00

112 lines
2.1 KiB
C

#ifndef __CR_ATOMIC_H__
#define __CR_ATOMIC_H__
/*
* PowerPC atomic operations
*
* Copied from kernel header file arch/powerpc/include/asm/atomic.h
*/
typedef struct {
int counter;
} atomic_t;
#include "asm/cmpxchg.h"
#define PPC_ATOMIC_ENTRY_BARRIER "lwsync \n"
#define PPC_ATOMIC_EXIT_BARRIER "sync \n"
#define ATOMIC_INIT(i) { (i) }
static __inline__ int atomic_read(const atomic_t *v)
{
int t;
__asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m"(v->counter));
return t;
}
static __inline__ void atomic_set(atomic_t *v, int i)
{
__asm__ __volatile__("stw%U0%X0 %1,%0" : "=m"(v->counter) : "r"(i));
}
#define ATOMIC_OP(op, asm_op) \
static __inline__ void atomic_##op(int a, atomic_t *v) \
{ \
int t; \
\
__asm__ __volatile__( \
"1: lwarx %0,0,%3 # atomic_" #op "\n" \
#asm_op " %0,%2,%0\n" \
" stwcx. %0,0,%3 \n" \
" bne- 1b\n" \
: "=&r" (t), "+m" (v->counter) \
: "r" (a), "r" (&v->counter) \
: "cc"); \
} \
ATOMIC_OP(add, add)
ATOMIC_OP(sub, subf)
#undef ATOMIC_OP
static __inline__ void atomic_inc(atomic_t *v)
{
int t;
__asm__ __volatile__(
"1: lwarx %0,0,%2 # atomic_inc\n\
addic %0,%0,1\n"
" stwcx. %0,0,%2 \n\
bne- 1b"
: "=&r" (t), "+m" (v->counter)
: "r" (&v->counter)
: "cc", "xer");
}
static __inline__ int atomic_inc_return(atomic_t *v)
{
int t;
__asm__ __volatile__(
PPC_ATOMIC_ENTRY_BARRIER \
"1: lwarx %0,0,%1 # atomic_inc_return\n\
addic %0,%0,1\n"
" stwcx. %0,0,%1 \n\
bne- 1b \n" \
PPC_ATOMIC_EXIT_BARRIER
: "=&r" (t)
: "r" (&v->counter)
: "cc", "xer", "memory");
return t;
}
/*
* atomic_inc_and_test - increment and test
* @v: pointer of type atomic_t
*
* Atomically increments @v by 1
* and returns true if the result is zero, or false for all
* other cases.
*/
static __inline__ void atomic_dec(atomic_t *v)
{
int t;
__asm__ __volatile__(
"1: lwarx %0,0,%2 # atomic_dec\n\
addic %0,%0,-1\n"
" stwcx. %0,0,%2\n\
bne- 1b"
: "=&r" (t), "+m" (v->counter)
: "r" (&v->counter)
: "cc", "xer");
}
#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n)))
#endif /* __CR_ATOMIC_H__ */