arm64: uti: Add arch-dependent helper for context switch
arm64 performs context-switch in kernel space instead of user space as in x86_64. Change-Id: Ib119b9ff014effb970183ee86cfac67fab773cba Futjitsu: POSTK_DEBUG_ARCH_DEP_99
This commit is contained in:
committed by
Masamichi Takagi
parent
63d500515a
commit
8356ef6c96
@ -55,7 +55,7 @@
|
|||||||
#define MCEXEC_UP_SYS_UNSHARE 0x30a02916
|
#define MCEXEC_UP_SYS_UNSHARE 0x30a02916
|
||||||
|
|
||||||
#define MCEXEC_UP_UTI_GET_CTX 0x30a02920
|
#define MCEXEC_UP_UTI_GET_CTX 0x30a02920
|
||||||
#define MCEXEC_UP_UTI_SAVE_FS 0x30a02921
|
#define MCEXEC_UP_UTI_SWITCH_CTX 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
|
||||||
|
|||||||
@ -1,7 +1,12 @@
|
|||||||
/* archdeps.c COPYRIGHT FUJITSU LIMITED 2016 */
|
/* archdeps.c COPYRIGHT FUJITSU LIMITED 2016-2019 */
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#include <linux/mm_types.h>
|
#include <linux/mm_types.h>
|
||||||
#include <linux/kallsyms.h>
|
#include <linux/kallsyms.h>
|
||||||
|
#if KERNEL_VERSION(4, 11, 0) <= LINUX_VERSION_CODE
|
||||||
|
#include <linux/sched/task_stack.h>
|
||||||
|
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) */
|
||||||
|
#include <linux/ptrace.h>
|
||||||
|
#include <linux/uaccess.h>
|
||||||
#include <asm/vdso.h>
|
#include <asm/vdso.h>
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "../../mcctrl.h"
|
#include "../../mcctrl.h"
|
||||||
@ -150,30 +155,11 @@ set_user_sp(void *usp)
|
|||||||
/* TODO; skeleton for UTI */
|
/* TODO; skeleton for UTI */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO; skeleton for UTI */
|
|
||||||
struct trans_uctx {
|
struct trans_uctx {
|
||||||
volatile int cond;
|
volatile int cond;
|
||||||
int fregsize;
|
int fregsize;
|
||||||
|
struct user_pt_regs regs;
|
||||||
unsigned long rax;
|
unsigned long tls_baseaddr;
|
||||||
unsigned long rbx;
|
|
||||||
unsigned long rcx;
|
|
||||||
unsigned long rdx;
|
|
||||||
unsigned long rsi;
|
|
||||||
unsigned long rdi;
|
|
||||||
unsigned long rbp;
|
|
||||||
unsigned long r8;
|
|
||||||
unsigned long r9;
|
|
||||||
unsigned long r10;
|
|
||||||
unsigned long r11;
|
|
||||||
unsigned long r12;
|
|
||||||
unsigned long r13;
|
|
||||||
unsigned long r14;
|
|
||||||
unsigned long r15;
|
|
||||||
unsigned long rflags;
|
|
||||||
unsigned long rip;
|
|
||||||
unsigned long rsp;
|
|
||||||
unsigned long fs;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -302,3 +288,38 @@ out:
|
|||||||
error, rva, rpa, pgsize);
|
error, rva, rpa, pgsize);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assembler switch_ctx executes only ioctl.
|
||||||
|
* Context register save/load is done on Linux (get from current_pt_regs).
|
||||||
|
* Do TLS save/load and register host_thread with ioctl.
|
||||||
|
*/
|
||||||
|
long arch_switch_ctx(struct uti_save_fs_desc *desc)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct trans_uctx *__user rctx = NULL;
|
||||||
|
struct trans_uctx *__user lctx = NULL;
|
||||||
|
struct trans_uctx klctx = {
|
||||||
|
.regs = current_pt_regs()->user_regs,
|
||||||
|
};
|
||||||
|
|
||||||
|
rctx = desc->rctx;
|
||||||
|
lctx = desc->lctx;
|
||||||
|
|
||||||
|
if (copy_to_user(lctx, &klctx, sizeof(klctx))) {
|
||||||
|
pr_err("%s: Error: copy_to_user failed\n", __func__);
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_from_user(¤t_pt_regs()->user_regs,
|
||||||
|
&rctx->regs, sizeof(rctx->regs))) {
|
||||||
|
pr_err("%s: Error: copy_from_user failed\n", __func__);
|
||||||
|
rc = -EFAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
restore_fs(get_fs_ctx(rctx));
|
||||||
|
|
||||||
|
out:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|||||||
@ -368,3 +368,11 @@ static inline bool pte_is_write_combined(pte_t pte)
|
|||||||
}
|
}
|
||||||
#endif /* POSTK_DEBUG_ARCH_DEP_12 */
|
#endif /* POSTK_DEBUG_ARCH_DEP_12 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The assembler switch_ctx is save/load registers in the context.
|
||||||
|
* Do FS save/load and register host_thread with ioctl.
|
||||||
|
*/
|
||||||
|
long arch_switch_ctx(struct uti_save_fs_desc *desc)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@ -319,17 +319,6 @@ struct mcos_handler_info;
|
|||||||
static LIST_HEAD(host_threads); /* Used for FS switch */
|
static LIST_HEAD(host_threads); /* Used for FS switch */
|
||||||
DEFINE_RWLOCK(host_thread_lock);
|
DEFINE_RWLOCK(host_thread_lock);
|
||||||
|
|
||||||
/* Info of Linux counterpart of migrated-to-Linux thread */
|
|
||||||
struct host_thread {
|
|
||||||
struct list_head list;
|
|
||||||
struct mcos_handler_info *handler;
|
|
||||||
int pid;
|
|
||||||
int tid;
|
|
||||||
unsigned long usp;
|
|
||||||
unsigned long lfs;
|
|
||||||
unsigned long rfs;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mcos_handler_info *new_mcos_handler_info(ihk_os_t os, struct file *file)
|
struct mcos_handler_info *new_mcos_handler_info(ihk_os_t os, struct file *file)
|
||||||
{
|
{
|
||||||
struct mcos_handler_info *info;
|
struct mcos_handler_info *info;
|
||||||
@ -2492,7 +2481,8 @@ long mcexec_uti_get_ctx(ihk_os_t os, struct uti_get_ctx_desc __user *udesc)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
long mcexec_uti_save_fs(ihk_os_t os, struct uti_save_fs_desc __user *udesc, struct file *file)
|
long mcctrl_switch_ctx(ihk_os_t os, struct uti_save_fs_desc __user *udesc,
|
||||||
|
struct file *file)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
void *usp = get_user_sp();
|
void *usp = get_user_sp();
|
||||||
@ -2509,12 +2499,17 @@ long mcexec_uti_save_fs(ihk_os_t os, struct uti_save_fs_desc __user *udesc, stru
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(copy_from_user(&desc, udesc, sizeof(struct uti_save_fs_desc))) {
|
if (copy_from_user(&desc, udesc, sizeof(struct uti_save_fs_desc))) {
|
||||||
printk("%s: Error: copy_from_user failed\n", __FUNCTION__);
|
printk("%s: Error: copy_from_user failed\n", __FUNCTION__);
|
||||||
rc = -EFAULT;
|
rc = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = arch_switch_ctx(&desc);
|
||||||
|
if (rc < 0) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
save_fs_ctx(desc.lctx);
|
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);
|
||||||
@ -3272,8 +3267,9 @@ long __mcctrl_control(ihk_os_t os, unsigned int req, unsigned long arg,
|
|||||||
case MCEXEC_UP_UTI_GET_CTX:
|
case MCEXEC_UP_UTI_GET_CTX:
|
||||||
return mcexec_uti_get_ctx(os, (struct uti_get_ctx_desc *)arg);
|
return mcexec_uti_get_ctx(os, (struct uti_get_ctx_desc *)arg);
|
||||||
|
|
||||||
case MCEXEC_UP_UTI_SAVE_FS:
|
case MCEXEC_UP_UTI_SWITCH_CTX:
|
||||||
return mcexec_uti_save_fs(os, (struct uti_save_fs_desc *)arg, file);
|
return mcctrl_switch_ctx(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);
|
||||||
|
|||||||
@ -86,7 +86,7 @@ static struct ihk_os_user_call_handler mcctrl_uchs[] = {
|
|||||||
{ .request = MCEXEC_UP_SYS_UNSHARE, .func = mcctrl_ioctl },
|
{ .request = MCEXEC_UP_SYS_UNSHARE, .func = mcctrl_ioctl },
|
||||||
#endif // MCEXEC_BIND_MOUNT
|
#endif // MCEXEC_BIND_MOUNT
|
||||||
{ .request = MCEXEC_UP_UTI_GET_CTX, .func = mcctrl_ioctl },
|
{ .request = MCEXEC_UP_UTI_GET_CTX, .func = mcctrl_ioctl },
|
||||||
{ .request = MCEXEC_UP_UTI_SAVE_FS, .func = mcctrl_ioctl },
|
{ .request = MCEXEC_UP_UTI_SWITCH_CTX, .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 },
|
||||||
|
|||||||
@ -124,12 +124,6 @@ enum mcctrl_os_cpu_operation {
|
|||||||
MCCTRL_OS_CPU_MAX_OP
|
MCCTRL_OS_CPU_MAX_OP
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Used to wake-up a Linux thread futex_wait()-ing */
|
|
||||||
struct uti_futex_resp {
|
|
||||||
int done;
|
|
||||||
wait_queue_head_t wq;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ikc_scd_packet {
|
struct ikc_scd_packet {
|
||||||
struct ihk_ikc_packet_header header;
|
struct ihk_ikc_packet_header header;
|
||||||
int msg;
|
int msg;
|
||||||
@ -570,4 +564,24 @@ struct mcctrl_ioctl_getrusage_desc {
|
|||||||
size_t size_rusage;
|
size_t size_rusage;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* uti */
|
||||||
|
long mcctrl_switch_ctx(ihk_os_t os, struct uti_save_fs_desc __user *desc,
|
||||||
|
struct file *file);
|
||||||
|
long arch_switch_ctx(struct uti_save_fs_desc *desc);
|
||||||
|
|
||||||
|
struct host_thread {
|
||||||
|
struct list_head list;
|
||||||
|
struct mcos_handler_info *handler;
|
||||||
|
int pid;
|
||||||
|
int tid;
|
||||||
|
unsigned long usp;
|
||||||
|
unsigned long lfs;
|
||||||
|
unsigned long rfs;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Used to wake-up a Linux thread futex_wait()-ing */
|
||||||
|
struct uti_futex_resp {
|
||||||
|
int done;
|
||||||
|
wait_queue_head_t wq;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
/* archdep.S COPYRIGHT FUJITSU LIMITED 2017-2018 */
|
/* archdep.S COPYRIGHT FUJITSU LIMITED 2017-2019 */
|
||||||
|
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
@ -11,6 +11,8 @@
|
|||||||
* x2 : void **param
|
* x2 : void **param
|
||||||
* x3 : void *lctx
|
* x3 : void *lctx
|
||||||
* x4 : void *rctx
|
* x4 : void *rctx
|
||||||
|
*
|
||||||
|
* Save and switch the context including TLS.
|
||||||
*/
|
*/
|
||||||
.global switch_ctx
|
.global switch_ctx
|
||||||
switch_ctx:
|
switch_ctx:
|
||||||
|
|||||||
@ -17,6 +17,8 @@ Syscam call convention:
|
|||||||
rdi: fd
|
rdi: fd
|
||||||
rsi: cmd
|
rsi: cmd
|
||||||
rdx: param
|
rdx: param
|
||||||
|
|
||||||
|
Save and switch the context including FS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.global switch_ctx
|
.global switch_ctx
|
||||||
|
|||||||
@ -2894,7 +2894,8 @@ static long util_thread(struct thread_data_s *my_thread, unsigned long rp_rctx,
|
|||||||
save_fs_desc.rctx = uti_desc->rctx;
|
save_fs_desc.rctx = uti_desc->rctx;
|
||||||
save_fs_desc.lctx = uti_desc->lctx;
|
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))
|
if ((rc = switch_ctx(fd, MCEXEC_UP_UTI_SWITCH_CTX, &save_fs_desc,
|
||||||
|
uti_desc->lctx, uti_desc->rctx))
|
||||||
< 0) {
|
< 0) {
|
||||||
fprintf(stderr, "%s: ERROR switch_ctx failed (%d)\n", __FUNCTION__, rc);
|
fprintf(stderr, "%s: ERROR switch_ctx failed (%d)\n", __FUNCTION__, rc);
|
||||||
goto out;
|
goto out;
|
||||||
|
|||||||
Reference in New Issue
Block a user