uti: Replace data types represented as arrays with C structures
Defining C structures for the following objects: (1) Remote and local context (2) Stack of system call arguments / return values Change-Id: Iafbb6c795bd765e3c78c54a255d8a1e4d4536288
This commit is contained in:
@@ -55,8 +55,8 @@
|
|||||||
#define MCEXEC_UP_SYS_UMOUNT 0x30a02915
|
#define MCEXEC_UP_SYS_UMOUNT 0x30a02915
|
||||||
#define MCEXEC_UP_SYS_UNSHARE 0x30a02916
|
#define MCEXEC_UP_SYS_UNSHARE 0x30a02916
|
||||||
|
|
||||||
#define MCEXEC_UP_UTIL_THREAD1 0x30a02920
|
#define MCEXEC_UP_UTI_GET_CTX 0x30a02920
|
||||||
#define MCEXEC_UP_UTIL_THREAD2 0x30a02921
|
#define MCEXEC_UP_UTI_SAVE_FS 0x30a02921
|
||||||
#define MCEXEC_UP_SIG_THREAD 0x30a02922
|
#define MCEXEC_UP_SIG_THREAD 0x30a02922
|
||||||
#define MCEXEC_UP_SYSCALL_THREAD 0x30a02924
|
#define MCEXEC_UP_SYSCALL_THREAD 0x30a02924
|
||||||
#define MCEXEC_UP_TERMINATE_THREAD 0x30a02925
|
#define MCEXEC_UP_TERMINATE_THREAD 0x30a02925
|
||||||
@@ -331,4 +331,26 @@ struct uti_attr_desc {
|
|||||||
unsigned long phys_attr;
|
unsigned long phys_attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct uti_ctx {
|
||||||
|
union {
|
||||||
|
char ctx[4096]; /* TODO: Get the size from config.h */
|
||||||
|
struct {
|
||||||
|
int uti_refill_tid;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uti_get_ctx_desc {
|
||||||
|
unsigned long rp_rctx; /* Remote physical address of remote context */
|
||||||
|
void *rctx; /* Remote context */
|
||||||
|
void *lctx; /* Local context */
|
||||||
|
int uti_refill_tid;
|
||||||
|
unsigned long key; /* OUT: struct task_struct* of mcexec thread, used to search struct host_thread */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct uti_save_fs_desc {
|
||||||
|
void *rctx; /* Remote context */
|
||||||
|
void *lctx; /* Local context */
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,17 +8,20 @@ struct syscall_struct {
|
|||||||
unsigned long uti_clv; /* copy of a clv in McKernel */
|
unsigned long uti_clv; /* copy of a clv in McKernel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define UTI_SZ_SYSCALL_STACK 16
|
||||||
|
|
||||||
/* Variables accessed by mcexec.c and syscall_intercept.c */
|
/* Variables accessed by mcexec.c and syscall_intercept.c */
|
||||||
struct uti_desc {
|
struct uti_desc {
|
||||||
void *wp; /* Syscall arguments list and record of McKernel context and Linux context */
|
char lctx[4096]; /* TODO: Get the size from config.h */
|
||||||
|
char rctx[4096]; /* TODO: Get the size from config.h */
|
||||||
int mck_tid; /* TODO: Move this out for multiple migrated-to-Linux threads */
|
int mck_tid; /* TODO: Move this out for multiple migrated-to-Linux threads */
|
||||||
unsigned long key; /* struct task_struct* of mcexec thread, used to search struct host_thread */
|
unsigned long key; /* struct task_struct* of mcexec thread, used to search struct host_thread */
|
||||||
int pid, tid; /* Used as the id of tracee when issuing MCEXEC_UP_TERMINATE_THREAD */
|
int pid, tid; /* Used as the id of tracee when issuing MCEXEC_UP_TERMINATE_THREAD */
|
||||||
unsigned long uti_clv; /* copy of McKernel clv */
|
unsigned long uti_clv; /* copy of McKernel clv */
|
||||||
|
|
||||||
int fd; /* /dev/mcosX */
|
int fd; /* /dev/mcosX */
|
||||||
struct syscall_struct *syscall_param_top; /* stack-pointer of syscall arguments list */
|
struct syscall_struct syscall_stack[UTI_SZ_SYSCALL_STACK]; /* stack of system call arguments and return values */
|
||||||
struct syscall_struct *syscall_param; /* TODO: make it auto variable */
|
int syscall_stack_top; /* stack-pointer of syscall arguments list */
|
||||||
long syscalls[512], syscalls2[512]; /* Syscall profile counters */
|
long syscalls[512], syscalls2[512]; /* Syscall profile counters */
|
||||||
int start_syscall_intercept; /* Used to sync between mcexec.c and syscall_intercept.c */
|
int start_syscall_intercept; /* Used to sync between mcexec.c and syscall_intercept.c */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -279,6 +279,14 @@ get_fs_ctx(void *ctx)
|
|||||||
return tctx->fs;
|
return tctx->fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long
|
||||||
|
get_rsp_ctx(void *ctx)
|
||||||
|
{
|
||||||
|
struct trans_uctx *tctx = ctx;
|
||||||
|
|
||||||
|
return tctx->rsp;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef POSTK_DEBUG_ARCH_DEP_83 /* arch depend translate_rva_to_rpa() move */
|
#ifdef POSTK_DEBUG_ARCH_DEP_83 /* arch depend translate_rva_to_rpa() move */
|
||||||
int translate_rva_to_rpa(ihk_os_t os, unsigned long rpt, unsigned long rva,
|
int translate_rva_to_rpa(ihk_os_t os, unsigned long rpt, unsigned long rva,
|
||||||
unsigned long *rpap, unsigned long *pgsizep)
|
unsigned long *rpap, unsigned long *pgsizep)
|
||||||
|
|||||||
@@ -1246,6 +1246,9 @@ int mcexec_syscall(struct mcctrl_usrdata *ud, struct ikc_scd_packet *packet)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!wqhln) {
|
||||||
|
dprintk("%s: uti: INFO: target worker (tid=%d) not found in wq_list\n", __FUNCTION__, packet->req.ttid);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!wqhln) {
|
if (!wqhln) {
|
||||||
printk("%s: WARNING: no target thread (tid=%d) found for exact request??\n",
|
printk("%s: WARNING: no target thread (tid=%d) found for exact request??\n",
|
||||||
@@ -2386,76 +2389,76 @@ extern void set_user_sp(unsigned long);
|
|||||||
extern void restore_fs(unsigned long fs);
|
extern void restore_fs(unsigned long fs);
|
||||||
extern void save_fs_ctx(void *);
|
extern void save_fs_ctx(void *);
|
||||||
extern unsigned long get_fs_ctx(void *);
|
extern unsigned long get_fs_ctx(void *);
|
||||||
|
extern unsigned long get_rsp_ctx(void *);
|
||||||
|
|
||||||
long
|
long mcexec_uti_get_ctx(ihk_os_t os, struct uti_get_ctx_desc __user *udesc)
|
||||||
mcexec_util_thread1(ihk_os_t os, unsigned long arg, struct file *file)
|
|
||||||
{
|
{
|
||||||
void **__user uparam = (void ** __user)arg;
|
struct uti_get_ctx_desc desc;
|
||||||
void *param[7];
|
|
||||||
unsigned long p_rctx;
|
|
||||||
unsigned long phys;
|
unsigned long phys;
|
||||||
void *__user u_rctx;
|
struct uti_ctx *rctx;
|
||||||
void *rctx;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
unsigned long free_address;
|
|
||||||
unsigned long free_size;
|
|
||||||
unsigned long icurrent = (unsigned long)current;
|
unsigned long icurrent = (unsigned long)current;
|
||||||
|
|
||||||
if(copy_from_user(param, uparam, sizeof(void *) * 7)) {
|
if(copy_from_user(&desc, udesc, sizeof(struct uti_get_ctx_desc))) {
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
p_rctx = (unsigned long)param[0];
|
|
||||||
u_rctx = (void *__user)param[1];
|
|
||||||
free_address = (unsigned long)param[4];
|
|
||||||
free_size = (unsigned long)param[5];
|
|
||||||
|
|
||||||
phys = ihk_device_map_memory(ihk_os_to_dev(os), p_rctx, PAGE_SIZE);
|
|
||||||
#ifdef CONFIG_MIC
|
|
||||||
rctx = ioremap_wc(phys, PAGE_SIZE);
|
|
||||||
#else
|
|
||||||
rctx = ihk_device_map_virtual(ihk_os_to_dev(os), phys, PAGE_SIZE, NULL, 0);
|
|
||||||
#endif
|
|
||||||
if(copy_to_user(u_rctx, rctx, PAGE_SIZE) ||
|
|
||||||
copy_to_user((unsigned long *)(uparam + 3), &icurrent,
|
|
||||||
sizeof(unsigned long)))
|
|
||||||
rc = -EFAULT;
|
rc = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
((unsigned long *)rctx)[0] = free_address;
|
phys = ihk_device_map_memory(ihk_os_to_dev(os), desc.rp_rctx, sizeof(struct uti_ctx));
|
||||||
((unsigned long *)rctx)[1] = free_size;
|
#ifdef CONFIG_MIC
|
||||||
((unsigned long *)rctx)[2] = (unsigned long)param[6];
|
rctx = ioremap_wc(phys, sizeof(struct uti_ctx));
|
||||||
|
#else
|
||||||
|
rctx = ihk_device_map_virtual(ihk_os_to_dev(os), phys, sizeof(struct uti_ctx), NULL, 0);
|
||||||
|
#endif
|
||||||
|
if (copy_to_user(desc.rctx, rctx->ctx, sizeof(struct uti_ctx))) {
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto unmap_and_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_to_user(&udesc->key, &icurrent, sizeof(unsigned long))) {
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto unmap_and_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rctx->uti_refill_tid = desc.uti_refill_tid;
|
||||||
|
|
||||||
|
unmap_and_out:
|
||||||
#ifdef CONFIG_MIC
|
#ifdef CONFIG_MIC
|
||||||
iounmap(rctx);
|
iounmap(rctx);
|
||||||
#else
|
#else
|
||||||
ihk_device_unmap_virtual(ihk_os_to_dev(os), rctx, PAGE_SIZE);
|
ihk_device_unmap_virtual(ihk_os_to_dev(os), rctx, sizeof(struct uti_ctx));
|
||||||
#endif
|
#endif
|
||||||
ihk_device_unmap_memory(ihk_os_to_dev(os), phys, PAGE_SIZE);
|
ihk_device_unmap_memory(ihk_os_to_dev(os), phys, sizeof(struct uti_ctx));
|
||||||
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
long
|
long mcexec_uti_save_fs(ihk_os_t os, struct uti_save_fs_desc __user *udesc, struct file *file)
|
||||||
mcexec_util_thread2(ihk_os_t os, unsigned long arg, struct file *file)
|
|
||||||
{
|
{
|
||||||
|
int rc = 0;
|
||||||
void *usp = get_user_sp();
|
void *usp = get_user_sp();
|
||||||
struct mcos_handler_info *info;
|
struct mcos_handler_info *info;
|
||||||
struct host_thread *thread;
|
struct host_thread *thread;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
void **__user param = (void **__user )arg;
|
struct uti_save_fs_desc desc;
|
||||||
void *__user rctx = (void *__user)param[1];
|
|
||||||
void *__user lctx = (void *__user)param[2];
|
|
||||||
struct mcctrl_usrdata *usrdata = ihk_host_os_get_usrdata(os);
|
struct mcctrl_usrdata *usrdata = ihk_host_os_get_usrdata(os);
|
||||||
struct mcctrl_per_proc_data *ppd;
|
struct mcctrl_per_proc_data *ppd;
|
||||||
|
|
||||||
save_fs_ctx(lctx);
|
if(copy_from_user(&desc, udesc, sizeof(struct uti_save_fs_desc))) {
|
||||||
|
printk("%s: Error: copy_from_user failed\n", __FUNCTION__);
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
save_fs_ctx(desc.lctx);
|
||||||
info = ihk_os_get_mcos_private_data(file);
|
info = ihk_os_get_mcos_private_data(file);
|
||||||
thread = kmalloc(sizeof(struct host_thread), GFP_KERNEL);
|
thread = kmalloc(sizeof(struct host_thread), GFP_KERNEL);
|
||||||
memset(thread, '\0', sizeof(struct host_thread));
|
memset(thread, '\0', sizeof(struct host_thread));
|
||||||
thread->pid = task_tgid_vnr(current);
|
thread->pid = task_tgid_vnr(current);
|
||||||
thread->tid = task_pid_vnr(current);
|
thread->tid = task_pid_vnr(current);
|
||||||
thread->usp = (unsigned long)usp;
|
thread->usp = (unsigned long)usp;
|
||||||
thread->lfs = get_fs_ctx(lctx);
|
thread->lfs = get_fs_ctx(desc.lctx);
|
||||||
thread->rfs = get_fs_ctx(rctx);
|
thread->rfs = get_fs_ctx(desc.rctx);
|
||||||
thread->handler = info;
|
thread->handler = info;
|
||||||
|
|
||||||
write_lock_irqsave(&host_thread_lock, flags);
|
write_lock_irqsave(&host_thread_lock, flags);
|
||||||
@@ -2477,7 +2480,8 @@ mcexec_util_thread2(ihk_os_t os, unsigned long arg, struct file *file)
|
|||||||
*/
|
*/
|
||||||
ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current));
|
ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current));
|
||||||
pr_ppd("get", task_pid_vnr(current), ppd);
|
pr_ppd("get", task_pid_vnr(current), ppd);
|
||||||
return 0;
|
out:
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return value: 0 if target is uti thread, -EINVAL if not */
|
/* Return value: 0 if target is uti thread, -EINVAL if not */
|
||||||
@@ -3118,11 +3122,11 @@ long __mcctrl_control(ihk_os_t os, unsigned int req, unsigned long arg,
|
|||||||
case MCEXEC_UP_SYS_UNSHARE:
|
case MCEXEC_UP_SYS_UNSHARE:
|
||||||
return mcexec_sys_unshare((struct sys_unshare_desc *)arg);
|
return mcexec_sys_unshare((struct sys_unshare_desc *)arg);
|
||||||
|
|
||||||
case MCEXEC_UP_UTIL_THREAD1:
|
case MCEXEC_UP_UTI_GET_CTX:
|
||||||
return mcexec_util_thread1(os, arg, file);
|
return mcexec_uti_get_ctx(os, (struct uti_get_ctx_desc *)arg);
|
||||||
|
|
||||||
case MCEXEC_UP_UTIL_THREAD2:
|
case MCEXEC_UP_UTI_SAVE_FS:
|
||||||
return mcexec_util_thread2(os, arg, file);
|
return mcexec_uti_save_fs(os, (struct uti_save_fs_desc *)arg, file);
|
||||||
|
|
||||||
case MCEXEC_UP_SIG_THREAD:
|
case MCEXEC_UP_SIG_THREAD:
|
||||||
return mcexec_sig_thread(os, arg, file);
|
return mcexec_sig_thread(os, arg, file);
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ static struct ihk_os_user_call_handler mcctrl_uchs[] = {
|
|||||||
{ .request = MCEXEC_UP_SYS_MOUNT, .func = mcctrl_ioctl },
|
{ .request = MCEXEC_UP_SYS_MOUNT, .func = mcctrl_ioctl },
|
||||||
{ .request = MCEXEC_UP_SYS_UMOUNT, .func = mcctrl_ioctl },
|
{ .request = MCEXEC_UP_SYS_UMOUNT, .func = mcctrl_ioctl },
|
||||||
{ .request = MCEXEC_UP_SYS_UNSHARE, .func = mcctrl_ioctl },
|
{ .request = MCEXEC_UP_SYS_UNSHARE, .func = mcctrl_ioctl },
|
||||||
{ .request = MCEXEC_UP_UTIL_THREAD1, .func = mcctrl_ioctl },
|
{ .request = MCEXEC_UP_UTI_GET_CTX, .func = mcctrl_ioctl },
|
||||||
{ .request = MCEXEC_UP_UTIL_THREAD2, .func = mcctrl_ioctl },
|
{ .request = MCEXEC_UP_UTI_SAVE_FS, .func = mcctrl_ioctl },
|
||||||
{ .request = MCEXEC_UP_SIG_THREAD, .func = mcctrl_ioctl },
|
{ .request = MCEXEC_UP_SIG_THREAD, .func = mcctrl_ioctl },
|
||||||
{ .request = MCEXEC_UP_SYSCALL_THREAD, .func = mcctrl_ioctl },
|
{ .request = MCEXEC_UP_SYSCALL_THREAD, .func = mcctrl_ioctl },
|
||||||
{ .request = MCEXEC_UP_TERMINATE_THREAD, .func = mcctrl_ioctl },
|
{ .request = MCEXEC_UP_TERMINATE_THREAD, .func = mcctrl_ioctl },
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
/*
|
/*
|
||||||
arg: rdi, rsi, rdx, rcx, r8, r9
|
Calling convention:
|
||||||
ret: rax
|
arg: rdi, rsi, rdx, rcx, r8, r9
|
||||||
|
ret: rax
|
||||||
|
|
||||||
rax syscall number
|
rdi: fd
|
||||||
syscall: (rax:num) rdi rsi rdx r10 r8 r9 (rcx:ret addr)
|
rsi: cmd
|
||||||
fd, cmd, param
|
rdx: param
|
||||||
rdi: fd
|
rcx: save area
|
||||||
rsi: cmd
|
r8: new thread context
|
||||||
rdx: param
|
|
||||||
rcx: save area
|
Syscam call convention:
|
||||||
r8: new thread context
|
syscall number: rax
|
||||||
|
arg: rdi, rsi, rdx, r10, r8, r9
|
||||||
|
return addr: rcx
|
||||||
|
|
||||||
|
rdi: fd
|
||||||
|
rsi: cmd
|
||||||
|
rdx: param
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.global switch_ctx
|
.global switch_ctx
|
||||||
@@ -91,6 +98,7 @@ switch_ctx:
|
|||||||
|
|
||||||
1:
|
1:
|
||||||
mov $0xffffffffffffffff,%eax
|
mov $0xffffffffffffffff,%eax
|
||||||
|
retq
|
||||||
2:
|
2:
|
||||||
pushq %rax
|
pushq %rax
|
||||||
movq $158,%rax /* arch_prctl */
|
movq $158,%rax /* arch_prctl */
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
extern int switch_ctx(int fd, unsigned long cmd, void **param, void *lctx, void *rctx);
|
#include "../include/uprotocol.h"
|
||||||
|
|
||||||
|
extern int switch_ctx(int fd, unsigned long cmd, struct uti_save_fs_desc *desc, void *lctx, void *rctx);
|
||||||
extern unsigned long compare_and_swap(unsigned long *addr, unsigned long old, unsigned long new);
|
extern unsigned long compare_and_swap(unsigned long *addr, unsigned long old, unsigned long new);
|
||||||
extern unsigned int compare_and_swap_int(unsigned int *addr, unsigned int old, unsigned int new);
|
extern unsigned int compare_and_swap_int(unsigned int *addr, unsigned int old, unsigned int new);
|
||||||
extern int archdep_syscall(struct syscall_wait_desc *w, long *ret);
|
extern int archdep_syscall(struct syscall_wait_desc *w, long *ret);
|
||||||
|
|||||||
@@ -2881,18 +2881,18 @@ static void kill_thread(unsigned long tid, int sig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static long util_thread(struct thread_data_s *my_thread, unsigned long uctx_pa, int remote_tid, unsigned long pattr, unsigned long uti_clv, unsigned long _uti_desc)
|
static long util_thread(struct thread_data_s *my_thread, unsigned long rp_rctx, int remote_tid, unsigned long pattr, unsigned long uti_clv, unsigned long _uti_desc)
|
||||||
{
|
{
|
||||||
int i;
|
struct uti_get_ctx_desc get_ctx_desc;
|
||||||
void *lctx;
|
struct uti_save_fs_desc save_fs_desc;
|
||||||
void *rctx;
|
|
||||||
void *param[7];
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
void *uti_wp = (void*)-1;
|
|
||||||
|
struct thread_data_s *tp;
|
||||||
|
|
||||||
pthread_barrier_init(&uti_init_ready, NULL, 2);
|
pthread_barrier_init(&uti_init_ready, NULL, 2);
|
||||||
if ((rc = create_worker_thread(&tp, &uti_init_ready))) {
|
if ((rc = create_worker_thread(&tp, &uti_init_ready))) {
|
||||||
printf("%s: Error: create_worker_thread failed (%d)\n", __FUNCTION__, rc);
|
printf("%s: Error: create_worker_thread failed (%d)\n", __FUNCTION__, rc);
|
||||||
|
rc = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
pthread_barrier_wait(&uti_init_ready);
|
pthread_barrier_wait(&uti_init_ready);
|
||||||
@@ -2900,18 +2900,12 @@ static long util_thread(struct thread_data_s *my_thread, unsigned long uctx_pa,
|
|||||||
|
|
||||||
uti_desc = (struct uti_desc *)_uti_desc;
|
uti_desc = (struct uti_desc *)_uti_desc;
|
||||||
if (!uti_desc) {
|
if (!uti_desc) {
|
||||||
fprintf(stderr, "%s: ERROR: uti_desc isn't set. Use mcexec.sh instead of mcexec\n", __FUNCTION__);
|
printf("%s: ERROR: uti_desc isn't set. Use mcexec.sh instead of mcexec\n", __FUNCTION__);
|
||||||
exit(1);
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize uti related variables for syscall_intercept */
|
/* Initialize uti related variables for syscall_intercept */
|
||||||
|
|
||||||
uti_wp = mmap(NULL, PAGE_SIZE * 3, PROT_READ | PROT_WRITE,
|
|
||||||
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
|
||||||
if (uti_wp == (void *)-1) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
uti_desc->fd = fd;
|
uti_desc->fd = fd;
|
||||||
|
|
||||||
rc = syscall(888);
|
rc = syscall(888);
|
||||||
@@ -2919,42 +2913,21 @@ static long util_thread(struct thread_data_s *my_thread, unsigned long uctx_pa,
|
|||||||
fprintf(stderr, "%s: WARNING: syscall_intercept returned %x\n", __FUNCTION__, rc);
|
fprintf(stderr, "%s: WARNING: syscall_intercept returned %x\n", __FUNCTION__, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the context of the thread migrating to Linux */
|
/* Get the remote context, record refill tid */
|
||||||
#ifdef POSTK_DEBUG_ARCH_DEP_35
|
get_ctx_desc.rp_rctx = rp_rctx;
|
||||||
lctx = (char *)uti_wp + page_size;
|
get_ctx_desc.rctx = uti_desc->rctx;
|
||||||
rctx = (char *)lctx + page_size;
|
get_ctx_desc.lctx = uti_desc->lctx;
|
||||||
#else
|
get_ctx_desc.uti_refill_tid = tp->tid;
|
||||||
lctx = (char *)uti_wp + PAGE_SIZE;
|
|
||||||
rctx = (char *)lctx + PAGE_SIZE;
|
|
||||||
#endif /* POSTK_DEBUG_ARCH_DEP_35 */
|
|
||||||
|
|
||||||
param[0] = (void *)uctx_pa; /* Source address, kernel space */
|
if ((rc = ioctl(fd, MCEXEC_UP_UTI_GET_CTX, &get_ctx_desc))) {
|
||||||
param[1] = rctx; /* Destination address, user space */
|
fprintf(stderr, "%s: Error: MCEXEC_UP_UTI_GET_CTX failed (%d)\n", __FUNCTION__, errno);
|
||||||
param[2] = lctx;
|
|
||||||
param[4] = uti_desc->wp;
|
|
||||||
#ifdef POSTK_DEBUG_ARCH_DEP_35
|
|
||||||
param[5] = (void *)(page_size * 3);
|
|
||||||
#else /* POSTK_DEBUG_ARCH_DEP_35 */
|
|
||||||
param[5] = (void *)(PAGE_SIZE * 3);
|
|
||||||
#endif /* POSTK_DEBUG_ARCH_DEP_35 */
|
|
||||||
param[6] = (void *)tp->tid;
|
|
||||||
printf("%s: param[6]=%ld,tid=%ld\n", __FUNCTION__, (long)param[6], (long)((void *)tp->tid));
|
|
||||||
|
|
||||||
__dprintf("%s: before MCEXEC_UP_UTIL_THREAD1\n", __FUNCTION__);
|
|
||||||
|
|
||||||
/* 1. Copy context from kernel space to user space
|
|
||||||
2. Write uti_wp addr, its size for McKernel to uctx_pa
|
|
||||||
Note that this overwrites context */
|
|
||||||
if ((rc = ioctl(fd, MCEXEC_UP_UTIL_THREAD1, param)) == -1) {
|
|
||||||
fprintf(stderr, "util_thread1: %d errno=%d\n", rc, errno);
|
|
||||||
rc = -errno;
|
rc = -errno;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record the info of the thread migrating to Linux */
|
/* Initialize uti thread info */
|
||||||
uti_desc->wp = uti_wp;
|
|
||||||
uti_desc->mck_tid = remote_tid;
|
uti_desc->mck_tid = remote_tid;
|
||||||
uti_desc->key = (unsigned long)param[3]; /* key to find thread, i.e. struct task_struct * */
|
uti_desc->key = get_ctx_desc.key;
|
||||||
uti_desc->pid = getpid();
|
uti_desc->pid = getpid();
|
||||||
uti_desc->tid = gettid();
|
uti_desc->tid = gettid();
|
||||||
uti_desc->uti_clv = uti_clv;
|
uti_desc->uti_clv = uti_clv;
|
||||||
@@ -2965,12 +2938,6 @@ static long util_thread(struct thread_data_s *my_thread, unsigned long uctx_pa,
|
|||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
for (i = 1; i <= 10; i++) {
|
|
||||||
uti_desc->syscall_param = (struct syscall_struct *)uti_desc->wp + i;
|
|
||||||
*(void **)uti_desc->syscall_param = uti_desc->syscall_param_top;
|
|
||||||
uti_desc->syscall_param_top = uti_desc->syscall_param;
|
|
||||||
}
|
|
||||||
memset(uti_desc->wp, '\0', sizeof(long));
|
|
||||||
|
|
||||||
if (pattr) {
|
if (pattr) {
|
||||||
struct uti_attr_desc desc;
|
struct uti_attr_desc desc;
|
||||||
@@ -2979,30 +2946,22 @@ static long util_thread(struct thread_data_s *my_thread, unsigned long uctx_pa,
|
|||||||
ioctl(fd, MCEXEC_UP_UTI_ATTR, &desc);
|
ioctl(fd, MCEXEC_UP_UTI_ATTR, &desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* McKernel would create the thread detached, so detach myself */
|
|
||||||
if ((rc = pthread_detach(my_thread->thread_id)) < 0) {
|
|
||||||
fprintf(stderr, "%s: ERROR pthread_detach returned %d\n", __FUNCTION__, rc);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
my_thread->detached = 1;
|
|
||||||
|
|
||||||
/* Start intercepting syscalls. Note that it dereferences pointers in uti_desc. */
|
/* Start intercepting syscalls. Note that it dereferences pointers in uti_desc. */
|
||||||
uti_desc->start_syscall_intercept = 1;
|
uti_desc->start_syscall_intercept = 1;
|
||||||
|
|
||||||
if ((rc = switch_ctx(fd, MCEXEC_UP_UTIL_THREAD2, param, lctx, rctx))
|
/* Save remote and local FS and then contex-switch */
|
||||||
|
save_fs_desc.rctx = uti_desc->rctx;
|
||||||
|
save_fs_desc.lctx = uti_desc->lctx;
|
||||||
|
|
||||||
|
if ((rc = switch_ctx(fd, MCEXEC_UP_UTI_SAVE_FS, &save_fs_desc, uti_desc->lctx, uti_desc->rctx))
|
||||||
< 0) {
|
< 0) {
|
||||||
fprintf(stderr, "%s: ERROR switch_ctx returned %d\n", __FUNCTION__, rc);
|
fprintf(stderr, "%s: ERROR switch_ctx failed (%d)\n", __FUNCTION__, rc);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "return from util_thread2 rc=%d\n", rc);
|
fprintf(stderr, "%s: ERROR: Returned from switch_ctx (%d)\n", __FUNCTION__, rc);
|
||||||
pthread_exit(NULL);
|
rc = -EINVAL;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (uti_desc != (void*)-1 && uti_desc->wp != (void*)-1)
|
|
||||||
#ifdef POSTK_DEBUG_ARCH_DEP_35
|
|
||||||
munmap(uti_desc->wp, page_size * 3);
|
|
||||||
#else /* POSTK_DEBUG_ARCH_DEP_35 */
|
|
||||||
munmap(uti_desc->wp, PAGE_SIZE * 3);
|
|
||||||
#endif /* POSTK_DEBUG_ARCH_DEP_35 */
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4078,10 +4037,8 @@ return_execve2:
|
|||||||
w.sr.args[2], w.sr.args[3], w.sr.args[4]);
|
w.sr.args[2], w.sr.args[3], w.sr.args[4]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ret = munmap((void *)w.sr.args[1],
|
__eprintf("__NR_sched_setaffinity: invalid argument (%lx)\n", w.sr.args[0]);
|
||||||
w.sr.args[2]);
|
ret = -EINVAL;
|
||||||
if (ret == -1)
|
|
||||||
ret = -errno;
|
|
||||||
}
|
}
|
||||||
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
do_syscall_return(fd, cpu, ret, 0, 0, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ hook(long syscall_number,
|
|||||||
int tid = uti_syscall0(__NR_gettid);
|
int tid = uti_syscall0(__NR_gettid);
|
||||||
struct terminate_thread_desc term_desc;
|
struct terminate_thread_desc term_desc;
|
||||||
unsigned long code;
|
unsigned long code;
|
||||||
|
int stack_top;
|
||||||
|
|
||||||
if (!uti_desc.start_syscall_intercept) {
|
if (!uti_desc.start_syscall_intercept) {
|
||||||
return 1; /* System call isn't taken over */
|
return 1; /* System call isn't taken over */
|
||||||
@@ -50,34 +51,40 @@ hook(long syscall_number,
|
|||||||
case __NR_munmap:
|
case __NR_munmap:
|
||||||
case __NR_mprotect:
|
case __NR_mprotect:
|
||||||
case __NR_mremap:
|
case __NR_mremap:
|
||||||
if (!uti_desc.syscall_param_top) {
|
/* Overflow check */
|
||||||
|
if (uti_desc.syscall_stack_top == -1) {
|
||||||
*result = -ENOMEM;
|
*result = -ENOMEM;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
/* Pop syscall_struct list for reentrant safety */
|
|
||||||
uti_desc.syscall_param = uti_desc.syscall_param_top;
|
|
||||||
uti_desc.syscall_param_top = *(void **)uti_desc.syscall_param;
|
|
||||||
|
|
||||||
uti_desc.syscall_param->number = syscall_number;
|
/* Sanity check */
|
||||||
uti_desc.syscall_param->args[0] = arg0;
|
if (uti_desc.syscall_stack_top < 0 || uti_desc.syscall_stack_top >= UTI_SZ_SYSCALL_STACK) {
|
||||||
uti_desc.syscall_param->args[1] = arg1;
|
*result = -EINVAL;
|
||||||
uti_desc.syscall_param->args[2] = arg2;
|
return 0;
|
||||||
uti_desc.syscall_param->args[3] = arg3;
|
|
||||||
uti_desc.syscall_param->args[4] = arg4;
|
|
||||||
uti_desc.syscall_param->args[5] = arg5;
|
|
||||||
uti_desc.syscall_param->uti_clv = uti_desc.uti_clv;
|
|
||||||
uti_desc.syscall_param->ret = -EINVAL;
|
|
||||||
uti_syscall3(__NR_ioctl, uti_desc.fd, MCEXEC_UP_SYSCALL_THREAD, (long)uti_desc.syscall_param);
|
|
||||||
*result = uti_desc.syscall_param->ret;
|
|
||||||
|
|
||||||
/* push syscall_struct list */
|
|
||||||
*(void **)uti_desc.syscall_param = uti_desc.syscall_param_top;
|
|
||||||
uti_desc.syscall_param_top = uti_desc.syscall_param;
|
|
||||||
|
|
||||||
return 0; /* System call is taken over */
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
/* Store the return value in the stack to prevent it from getting corrupted
|
||||||
|
when an interrupt happens just after ioctl() and before copying the return
|
||||||
|
value to *result */
|
||||||
|
stack_top = __sync_fetch_and_sub(&uti_desc.syscall_stack_top, 1);
|
||||||
|
|
||||||
|
uti_desc.syscall_stack[stack_top].number = syscall_number;
|
||||||
|
uti_desc.syscall_stack[stack_top].args[0] = arg0;
|
||||||
|
uti_desc.syscall_stack[stack_top].args[1] = arg1;
|
||||||
|
uti_desc.syscall_stack[stack_top].args[2] = arg2;
|
||||||
|
uti_desc.syscall_stack[stack_top].args[3] = arg3;
|
||||||
|
uti_desc.syscall_stack[stack_top].args[4] = arg4;
|
||||||
|
uti_desc.syscall_stack[stack_top].args[5] = arg5;
|
||||||
|
uti_desc.syscall_stack[stack_top].uti_clv = uti_desc.uti_clv;
|
||||||
|
uti_desc.syscall_stack[stack_top].ret = -EINVAL;
|
||||||
|
|
||||||
|
uti_syscall3(__NR_ioctl, uti_desc.fd, MCEXEC_UP_SYSCALL_THREAD, (long)(uti_desc.syscall_stack + stack_top));
|
||||||
|
*result = uti_desc.syscall_stack[stack_top].ret;
|
||||||
|
|
||||||
|
/* push syscall_struct list */
|
||||||
|
__sync_fetch_and_add(&uti_desc.syscall_stack_top, 1);
|
||||||
|
|
||||||
|
return 0; /* System call is taken over */
|
||||||
case __NR_exit_group:
|
case __NR_exit_group:
|
||||||
code = 0x100000000;
|
code = 0x100000000;
|
||||||
goto make_remote_thread_exit;
|
goto make_remote_thread_exit;
|
||||||
@@ -116,9 +123,13 @@ hook(long syscall_number,
|
|||||||
static __attribute__((constructor)) void
|
static __attribute__((constructor)) void
|
||||||
init(void)
|
init(void)
|
||||||
{
|
{
|
||||||
// Set up the callback function
|
/* Set up the callback function */
|
||||||
intercept_hook_point = hook;
|
intercept_hook_point = hook;
|
||||||
|
|
||||||
|
/* Initialize uti_desc */
|
||||||
|
uti_desc.syscall_stack_top = UTI_SZ_SYSCALL_STACK - 1;
|
||||||
|
|
||||||
|
/* Pass address of uti_desc to McKernel */
|
||||||
uti_syscall1(733, (unsigned long)&uti_desc);
|
uti_syscall1(733, (unsigned long)&uti_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -590,6 +590,15 @@ typedef struct uti_attr {
|
|||||||
uint64_t flags; /* Representing location and behavior hints by bitmap */
|
uint64_t flags; /* Representing location and behavior hints by bitmap */
|
||||||
} uti_attr_t;
|
} uti_attr_t;
|
||||||
|
|
||||||
|
struct uti_ctx {
|
||||||
|
union {
|
||||||
|
char ctx[4096];
|
||||||
|
struct {
|
||||||
|
int uti_refill_tid;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct move_pages_smp_req {
|
struct move_pages_smp_req {
|
||||||
unsigned long count;
|
unsigned long count;
|
||||||
const void **user_virt_addr;
|
const void **user_virt_addr;
|
||||||
|
|||||||
@@ -2632,7 +2632,7 @@ void __find_and_replace_tid(struct process *proc, struct thread *thread, int new
|
|||||||
|
|
||||||
proc->tids[i].thread = NULL;
|
proc->tids[i].thread = NULL;
|
||||||
proc->tids[i].tid = new_tid;
|
proc->tids[i].tid = new_tid;
|
||||||
kprintf("%s: tid %d (thread %p) has been relaced with tid %d\n",
|
dkprintf("%s: tid %d (thread %p) has been relaced with tid %d\n",
|
||||||
__FUNCTION__, thread->tid, thread, new_tid);
|
__FUNCTION__, thread->tid, thread, new_tid);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9114,14 +9114,12 @@ int util_show_syscall_profile()
|
|||||||
|
|
||||||
int util_thread(struct uti_attr *arg)
|
int util_thread(struct uti_attr *arg)
|
||||||
{
|
{
|
||||||
volatile unsigned long *context;
|
struct uti_ctx *rctx = NULL;
|
||||||
unsigned long pcontext;
|
unsigned long rp_rctx;
|
||||||
struct cpu_local_var *uti_clv;
|
struct cpu_local_var *uti_clv = NULL;
|
||||||
struct syscall_request request IHK_DMA_ALIGN;
|
struct syscall_request request IHK_DMA_ALIGN;
|
||||||
long rc;
|
long rc;
|
||||||
struct thread *thread = cpu_local_var(current);
|
struct thread *thread = cpu_local_var(current);
|
||||||
unsigned long free_address;
|
|
||||||
unsigned long free_size;
|
|
||||||
struct kuti_attr {
|
struct kuti_attr {
|
||||||
long parent_cpuid;
|
long parent_cpuid;
|
||||||
struct uti_attr attr;
|
struct uti_attr attr;
|
||||||
@@ -9129,25 +9127,25 @@ int util_thread(struct uti_attr *arg)
|
|||||||
|
|
||||||
thread->uti_state = UTI_STATE_PROLOGUE;
|
thread->uti_state = UTI_STATE_PROLOGUE;
|
||||||
|
|
||||||
context = (volatile unsigned long *)ihk_mc_alloc_pages(1,
|
rctx = kmalloc(sizeof(struct uti_ctx), IHK_MC_AP_NOWAIT);
|
||||||
IHK_MC_AP_NOWAIT);
|
if (!rctx) {
|
||||||
if (!context) {
|
rc = -ENOMEM;
|
||||||
return -ENOMEM;
|
goto out;
|
||||||
}
|
}
|
||||||
pcontext = virt_to_phys((void *)context);
|
rp_rctx = virt_to_phys((void *)rctx);
|
||||||
save_uctx((void *)context, NULL);
|
save_uctx((void *)rctx->ctx, NULL);
|
||||||
|
|
||||||
/* Create a copy of clv and replace clv with it when the Linux thread calls in a McKernel function */
|
/* Create a copy of clv and replace clv with it when the Linux thread calls in a McKernel function */
|
||||||
uti_clv = kmalloc(sizeof(struct cpu_local_var), IHK_MC_AP_NOWAIT);
|
uti_clv = kmalloc(sizeof(struct cpu_local_var), IHK_MC_AP_NOWAIT);
|
||||||
if (!uti_clv) {
|
if (!uti_clv) {
|
||||||
ihk_mc_free_pages((void *)context, 1);
|
rc = -ENOMEM;
|
||||||
return -ENOMEM;
|
goto out;
|
||||||
}
|
}
|
||||||
memcpy(uti_clv, get_this_cpu_local_var(), sizeof(struct cpu_local_var));
|
memcpy(uti_clv, get_this_cpu_local_var(), sizeof(struct cpu_local_var));
|
||||||
|
|
||||||
request.number = __NR_sched_setaffinity;
|
request.number = __NR_sched_setaffinity;
|
||||||
request.args[0] = 0;
|
request.args[0] = 0;
|
||||||
request.args[1] = pcontext;
|
request.args[1] = rp_rctx;
|
||||||
request.args[2] = 0;
|
request.args[2] = 0;
|
||||||
if (arg) {
|
if (arg) {
|
||||||
memcpy(&kattr.attr, arg, sizeof(struct uti_attr));
|
memcpy(&kattr.attr, arg, sizeof(struct uti_attr));
|
||||||
@@ -9164,14 +9162,15 @@ int util_thread(struct uti_attr *arg)
|
|||||||
|
|
||||||
util_show_syscall_profile();
|
util_show_syscall_profile();
|
||||||
|
|
||||||
/* These are written by mcexec_util_thread1() */
|
/* Save it before freed */
|
||||||
free_address = context[0];
|
thread->uti_refill_tid = rctx->uti_refill_tid;
|
||||||
free_size = context[1];
|
dkprintf("%s: mcexec worker tid=%d\n", __FUNCTION__, thread->uti_refill_tid);
|
||||||
thread->uti_refill_tid = context[2];
|
|
||||||
dkprintf("%s: mcexec worker tid=%d\n", __FUNCTION__, context[2]);
|
kfree(rctx);
|
||||||
|
rctx = NULL;
|
||||||
|
|
||||||
ihk_mc_free_pages((void *)context, 1);
|
|
||||||
kfree(uti_clv);
|
kfree(uti_clv);
|
||||||
|
uti_clv = NULL;
|
||||||
|
|
||||||
if (rc >= 0) {
|
if (rc >= 0) {
|
||||||
if (rc & 0x100000000) { /* exit_group */
|
if (rc & 0x100000000) { /* exit_group */
|
||||||
@@ -9181,11 +9180,6 @@ int util_thread(struct uti_attr *arg)
|
|||||||
} else {
|
} else {
|
||||||
/* exit or killed-by-signal detected */
|
/* exit or killed-by-signal detected */
|
||||||
dkprintf("%s: exit or killed by signal, pid=%d,tid=%d,rc=%lx\n", __FUNCTION__, thread->proc->pid, thread->tid, rc);
|
dkprintf("%s: exit or killed by signal, pid=%d,tid=%d,rc=%lx\n", __FUNCTION__, thread->proc->pid, thread->tid, rc);
|
||||||
request.number = __NR_sched_setaffinity;
|
|
||||||
request.args[0] = 1;
|
|
||||||
request.args[1] = free_address;
|
|
||||||
request.args[2] = free_size;
|
|
||||||
do_syscall(&request, ihk_mc_get_processor_id(), 0);
|
|
||||||
do_exit(rc);
|
do_exit(rc);
|
||||||
}
|
}
|
||||||
} else if (rc == -ERESTARTSYS) {
|
} else if (rc == -ERESTARTSYS) {
|
||||||
@@ -9194,8 +9188,17 @@ int util_thread(struct uti_attr *arg)
|
|||||||
thread->proc->nohost = 1;
|
thread->proc->nohost = 1;
|
||||||
do_exit(rc);
|
do_exit(rc);
|
||||||
} else {
|
} else {
|
||||||
kprintf("%s: unknown error (%ld)\n", __FUNCTION__, rc);
|
kprintf("%s: ERROR: do_syscall() failed (%ld)\n", __FUNCTION__, rc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (rctx) {
|
||||||
|
kfree(rctx);
|
||||||
|
}
|
||||||
|
if (uti_clv) {
|
||||||
|
kfree(uti_clv);
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user