Yikun Jiang a68570b5d9 Add computing offloading code
1. Add computing offloading code
2. Add script.md
3. Add virsh_demo.xml

Change-Id: Id9ef883e2f0eb727eb5448b9d1c47767f46b1021
Signed-off-by: Yikun Jiang <yikunkero@gmail.com>
2023-10-23 19:29:57 +08:00

203 lines
5.7 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2023. Huawei Technologies Co., Ltd. All rights reserved.
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include "conn.h"
#include "log.h"
#include "qtfs_utils.h"
#include "req.h"
#include "qtfs-mod.h"
#ifndef QTFS_CLIENT
#error "QTFS utils only use in qtfs client."
#endif
long qtfs_utils_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
long qtfs_capability_ioctl(struct qtfs_conn_var_s *pvar, struct file *file, unsigned int cmd, unsigned long arg);
long qtfs_syscall_ioctl(struct qtfs_conn_var_s *pvar, struct file *file, unsigned int cmd, unsigned long arg);
struct file_operations qtfs_utils_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = qtfs_utils_ioctl,
};
static struct miscdevice qtfs_utils_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "qtfs_utils",
.fops = &qtfs_utils_fops,
};
int qtfs_utils_register(void)
{
int ret = misc_register(&qtfs_utils_dev);
if (ret) {
qtfs_err("qtfs utils dev register failed, ret:%d", ret);
return -EFAULT;
}
return 0;
}
void qtfs_utils_destroy(void)
{
misc_deregister(&qtfs_utils_dev);
return;
}
long qtfs_utils_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret = -EINVAL;
struct qtfs_conn_var_s *pvar = qtfs_conn_get_param();
if (pvar == NULL) {
qtfs_err("utils ioctl get pvar failed, cmd type:%c nr:%d", _IOC_TYPE(cmd), _IOC_NR(cmd));
return -EFAULT;
}
switch (_IOC_TYPE(cmd)) {
case QTUTIL_IOCTL_CAPA_MAGIC:
ret = qtfs_capability_ioctl(pvar, file, cmd, arg);
qtfs_info("utils capability ioctl nr:%d", _IOC_NR(cmd));
break;
case QTUTIL_IOCTL_SC_MAGIC:
ret = qtfs_syscall_ioctl(pvar, file, cmd, arg);
qtfs_info("utils syscall ioctl nr:%d", _IOC_NR(cmd));
break;
default:
qtfs_err("Unsupport magic type:%c", _IOC_TYPE(cmd));
break;
}
qtfs_conn_put_param(pvar);
return ret;
}
long qtfs_capability_ioctl(struct qtfs_conn_var_s *pvar, struct file *file, unsigned int cmd, unsigned long arg)
{
long ret = -ENOTSUPP;
return ret;
}
static long qtfs_sc_kill(struct qtfs_conn_var_s *pvar, unsigned long arg)
{
struct qtreq_sc_kill *req;
struct qtrsp_sc_kill *rsp;
struct qtsc_kill karg;
if (copy_from_user(&karg, (void *)arg, sizeof(struct qtsc_kill))) {
qtfs_err("copy args failed.");
return -EINVAL;
}
req = pvar->conn_ops->get_conn_msg_buf(pvar, QTFS_SEND);
req->pid = karg.pid;
req->signum = karg.signum;
rsp = qtfs_remote_run(pvar, QTFS_SC_KILL, sizeof(struct qtreq_sc_kill));
if (IS_ERR_OR_NULL(rsp)) {
qtfs_err("qtfs remote kill faile.");
return -EFAULT;
}
qtfs_info("qtfs remote kill pid:%d sig:%d success:%ld", req->pid, req->signum, rsp->ret);
return rsp->ret;
}
static long qtfs_sc_setaffinity(struct qtfs_conn_var_s *pvar, unsigned long arg)
{
struct qtreq_sc_sched_affinity *req;
struct qtrsp_sc_sched_affinity *rsp;
struct qtsc_sched_affinity karg;
if (copy_from_user(&karg, (void *)arg, sizeof(struct qtsc_sched_affinity))) {
qtfs_err("copy args failed.");
return -EINVAL;
}
req = pvar->conn_ops->get_conn_msg_buf(pvar, QTFS_SEND);
req->type = SC_SET;
req->pid = karg.pid;
req->len = (karg.len > AFFINITY_MAX_LEN) ? AFFINITY_MAX_LEN : karg.len;
if (copy_from_user(req->user_mask_ptr, karg.user_mask_ptr, req->len)) {
qtfs_err("copy from user mask ptr failed, len:%u", karg.len);
return -EFAULT;
}
rsp = qtfs_remote_run(pvar, QTFS_SC_SCHED_SETAFFINITY, sizeof(struct qtreq_sc_sched_affinity) + karg.len * sizeof(unsigned long));
if (IS_ERR_OR_NULL(rsp)) {
qtfs_err("qtfs remote set affinit failed, pid:%d len:%u", karg.pid, karg.len);
return -EFAULT;
}
qtfs_info("qtfs remote set affinity successed pid:%d len:%u return:%ld", karg.pid, karg.len, rsp->ret);
return rsp->ret;
}
static long qtfs_sc_getaffinity(struct qtfs_conn_var_s *pvar, unsigned long arg)
{
struct qtreq_sc_sched_affinity *req;
struct qtrsp_sc_sched_affinity *rsp;
struct qtsc_sched_affinity karg;
if (copy_from_user(&karg, (void *)arg, sizeof(struct qtsc_sched_affinity))) {
qtfs_err("copy args failed.");
return -EINVAL;
}
req = pvar->conn_ops->get_conn_msg_buf(pvar, QTFS_SEND);
req->type = SC_GET;
req->pid = karg.pid;
req->len = (karg.len > AFFINITY_MAX_LEN) ? AFFINITY_MAX_LEN : karg.len;
rsp = qtfs_remote_run(pvar, QTFS_SC_SCHED_GETAFFINITY, sizeof(struct qtreq_sc_sched_affinity));
if (IS_ERR_OR_NULL(rsp)) {
qtfs_err("qtfs remote get affinit failed, pid:%d len:%u", karg.pid, karg.len);
return -EFAULT;
}
// len == 0 means failed
if (rsp->len <= 0 || rsp->len > req->len ||
copy_to_user(karg.user_mask_ptr, rsp->user_mask_ptr, rsp->len)) {
qtfs_err("copy user mask ptr failed rsp len:%u valid len:%u", rsp->len, karg.len);
return -EINVAL;
}
return rsp->ret;
}
long qtfs_syscall_ioctl(struct qtfs_conn_var_s *pvar, struct file *file, unsigned int cmd, unsigned long arg)
{
long ret = -EINVAL;
switch (cmd) {
case QTUTIL_SC_KILL:
ret = qtfs_sc_kill(pvar, arg);
break;
case QTUTIL_SC_SCHED_SETAFFINITY:
ret = qtfs_sc_setaffinity(pvar, arg);
break;
case QTUTIL_SC_SCHED_GETAFFINITY:
ret = qtfs_sc_getaffinity(pvar, arg);
break;
default:
qtfs_err("syscall ioctl not support magic:%c number:%d", _IOC_TYPE(cmd), _IOC_NR(cmd));
break;
}
return ret;
}