mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-25 19:14:04 +00:00
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>
112 lines
2.1 KiB
C
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__ */
|