Commit 024bae0a authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Andrei Vagin

x86: add user_regs_native macro (optional)

This will document that {get,set}_user_reg should be used
only on initialized register set. Otherwise, after some code
changes we may find ourself in situation when setting not
inited user regs will set them for compatible register set:
(is_native == false).
Signed-off-by: 's avatarDmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 2aa583b4
...@@ -23,6 +23,8 @@ typedef struct user_fpsimd_state user_fpregs_struct_t; ...@@ -23,6 +23,8 @@ typedef struct user_fpsimd_state user_fpregs_struct_t;
#define REG_IP(r) ((uint64_t)(r).pc) #define REG_IP(r) ((uint64_t)(r).pc)
#define REG_SYSCALL_NR(r) ((uint64_t)(r).regs[8]) #define REG_SYSCALL_NR(r) ((uint64_t)(r).regs[8])
#define user_regs_native(pregs) true
/* /*
* Range for task size calculated from the following Linux kernel files: * Range for task size calculated from the following Linux kernel files:
* arch/arm64/include/asm/memory.h * arch/arm64/include/asm/memory.h
......
...@@ -57,6 +57,8 @@ struct user_vfp_exc { ...@@ -57,6 +57,8 @@ struct user_vfp_exc {
#define REG_IP(regs) ((regs).ARM_pc) #define REG_IP(regs) ((regs).ARM_pc)
#define REG_SYSCALL_NR(regs) ((regs).ARM_r7) #define REG_SYSCALL_NR(regs) ((regs).ARM_r7)
#define user_regs_native(pregs) true
/* /*
* Range for task size calculated from the following Linux kernel files: * Range for task size calculated from the following Linux kernel files:
* arch/arm/include/asm/memory.h * arch/arm/include/asm/memory.h
......
...@@ -76,6 +76,8 @@ typedef struct { ...@@ -76,6 +76,8 @@ typedef struct {
#define REG_IP(regs) ((uint64_t)(regs).nip) #define REG_IP(regs) ((uint64_t)(regs).nip)
#define REG_SYSCALL_NR(regs) ((uint64_t)(regs).gpr[0]) #define REG_SYSCALL_NR(regs) ((uint64_t)(regs).gpr[0])
#define user_regs_native(pregs) true
/* /*
* Copied from the following kernel header files : * Copied from the following kernel header files :
* include/linux/auxvec.h * include/linux/auxvec.h
......
...@@ -67,7 +67,7 @@ int arch_task_compatible(pid_t pid) ...@@ -67,7 +67,7 @@ int arch_task_compatible(pid_t pid)
if (ret) if (ret)
return -1; return -1;
return !r.is_native; return !user_regs_native(&r);
} }
#define USER32_CS 0x23 #define USER32_CS 0x23
...@@ -120,7 +120,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret, ...@@ -120,7 +120,7 @@ int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
user_regs_struct_t regs = ctl->orig.regs; user_regs_struct_t regs = ctl->orig.regs;
int err; int err;
if (regs.is_native) { if (user_regs_native(&regs)) {
user_regs_struct64 *r = &regs.native; user_regs_struct64 *r = &regs.native;
r->ax = (uint64_t)nr; r->ax = (uint64_t)nr;
...@@ -152,7 +152,7 @@ static int save_task_regs(CoreEntry *core, ...@@ -152,7 +152,7 @@ static int save_task_regs(CoreEntry *core,
user_regs_struct_t *regs, user_fpregs_struct_t *fpregs); user_regs_struct_t *regs, user_fpregs_struct_t *fpregs);
#define get_signed_user_reg(pregs, name) \ #define get_signed_user_reg(pregs, name) \
(((pregs)->is_native) ? (int64_t)((pregs)->native.name) : \ ((user_regs_native(pregs)) ? (int64_t)((pregs)->native.name) : \
(int32_t)((pregs)->compat.name)) (int32_t)((pregs)->compat.name))
int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core) int get_task_regs(pid_t pid, user_regs_struct_t regs, CoreEntry *core)
{ {
...@@ -222,7 +222,7 @@ static int save_task_regs(CoreEntry *core, ...@@ -222,7 +222,7 @@ static int save_task_regs(CoreEntry *core,
#define assign_reg(dst, src, e) do { dst->e = (__typeof__(dst->e))src.e; } while (0) #define assign_reg(dst, src, e) do { dst->e = (__typeof__(dst->e))src.e; } while (0)
#define assign_array(dst, src, e) memcpy(dst->e, &src.e, sizeof(src.e)) #define assign_array(dst, src, e) memcpy(dst->e, &src.e, sizeof(src.e))
if (regs.is_native) { if (user_regs_native(regs)) {
assign_reg(gpregs, regs->native, r15); assign_reg(gpregs, regs->native, r15);
assign_reg(gpregs, regs->native, r14); assign_reg(gpregs, regs->native, r14);
assign_reg(gpregs, regs->native, r13); assign_reg(gpregs, regs->native, r13);
...@@ -314,11 +314,11 @@ int ptrace_get_regs(pid_t pid, user_regs_struct_t *regs) ...@@ -314,11 +314,11 @@ int ptrace_get_regs(pid_t pid, user_regs_struct_t *regs)
ret = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov); ret = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov);
if (iov.iov_len == sizeof(regs->native)) { if (iov.iov_len == sizeof(regs->native)) {
regs->is_native = true; regs->__is_native = NATIVE_MAGIC;
return ret; return ret;
} }
if (iov.iov_len == sizeof(regs->compat)) { if (iov.iov_len == sizeof(regs->compat)) {
regs->is_native = false; regs->__is_native = COMPAT_MAGIC;
return ret; return ret;
} }
...@@ -332,7 +332,7 @@ int ptrace_set_regs(pid_t pid, user_regs_struct_t *regs) ...@@ -332,7 +332,7 @@ int ptrace_set_regs(pid_t pid, user_regs_struct_t *regs)
{ {
struct iovec iov; struct iovec iov;
if (regs->is_native) { if (user_regs_native(regs)) {
iov.iov_base = &regs->native; iov.iov_base = &regs->native;
iov.iov_len = sizeof(user_regs_struct64); iov.iov_len = sizeof(user_regs_struct64);
} else { } else {
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <signal.h> #include <signal.h>
#include "log.h"
#include "common/bug.h"
#include "common/page.h" #include "common/page.h"
#include "syscall-types.h" #include "syscall-types.h"
...@@ -61,27 +63,45 @@ typedef struct { ...@@ -61,27 +63,45 @@ typedef struct {
} user_regs_struct32; } user_regs_struct32;
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
/*
* To be sure that we rely on inited reg->__is_native, this member
* is (short int) instead of initial (bool). The right way to
* check if regs are native or compat is to use user_regs_native() macro.
* This should cost nothing, as *usually* sizeof(bool) == sizeof(short)
*/
typedef struct { typedef struct {
union { union {
user_regs_struct64 native; user_regs_struct64 native;
user_regs_struct32 compat; user_regs_struct32 compat;
}; };
bool is_native; short __is_native; /* use user_regs_native macro to check it */
} user_regs_struct_t; } user_regs_struct_t;
#define get_user_reg(pregs, name) (((pregs)->is_native) ? \
((pregs)->native.name) : \ #define NATIVE_MAGIC 0x0A
((pregs)->compat.name)) #define COMPAT_MAGIC 0x0C
#define set_user_reg(pregs, name, val) (((pregs)->is_native) ? \ static inline bool user_regs_native(user_regs_struct_t *pregs)
((pregs)->native.name = val) : \ {
((pregs)->compat.name = val)) return pregs->__is_native == NATIVE_MAGIC;
}
#define get_user_reg(pregs, name) \
((user_regs_native(pregs)) ? \
((pregs)->native.name) : \
((pregs)->compat.name))
#define set_user_reg(pregs, name, val) \
((user_regs_native(pregs)) ? \
((pregs)->native.name = (val)) : \
((pregs)->compat.name = (val)))
#else #else
typedef struct { typedef struct {
union { union {
user_regs_struct32 native; user_regs_struct32 native;
}; };
} user_regs_struct_t; } user_regs_struct_t;
#define get_user_reg(pregs, name) ((pregs)->native.name) #define user_regs_native(pregs) true
#define set_user_reg(pregs, name, val) ((pregs)->native.name = val) #define get_user_reg(pregs, name) ((pregs)->native.name)
#define set_user_reg(pregs, name, val) ((pregs)->native.name = val)
#endif #endif
#if 0 #if 0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment