提交 3084ffbd 编写于 作者: L Lijun Fang 提交者: Zheng Zengkai

svm: implement the process remap features

ascend inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4JMM0
CVE: NA

--------

This feature is to use debug the process memory.
Signed-off-by: NLijun Fang <fanglijun3@huawei.com>
Reviewed-by: NWeilong Chen <chenweilong@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 e68fca36
...@@ -36,12 +36,14 @@ ...@@ -36,12 +36,14 @@
#define SVM_DEVICE_NAME "svm" #define SVM_DEVICE_NAME "svm"
#define ASID_SHIFT 48 #define ASID_SHIFT 48
#define SVM_IOCTL_REMAP_PROC 0xfff4
#define SVM_IOCTL_LOAD_FLAG 0xfffa #define SVM_IOCTL_LOAD_FLAG 0xfffa
#define SVM_IOCTL_PROCESS_BIND 0xffff #define SVM_IOCTL_PROCESS_BIND 0xffff
#define CORE_SID 0 #define CORE_SID 0
#define SVM_IOCTL_RELEASE_PHYS32 0xfff3 #define SVM_IOCTL_RELEASE_PHYS32 0xfff3
#define SVM_REMAP_MEM_LEN_MAX (16 * 1024 * 1024)
#define MMAP_PHY32_MAX (16 * 1024 * 1024) #define MMAP_PHY32_MAX (16 * 1024 * 1024)
static int probe_index; static int probe_index;
...@@ -96,11 +98,21 @@ struct svm_process { ...@@ -96,11 +98,21 @@ struct svm_process {
struct iommu_sva *sva; struct iommu_sva *sva;
}; };
struct svm_proc_mem {
u32 dev_id;
u32 len;
u64 pid;
u64 vaddr;
u64 buf;
};
static char *svm_cmd_to_string(unsigned int cmd) static char *svm_cmd_to_string(unsigned int cmd)
{ {
switch (cmd) { switch (cmd) {
case SVM_IOCTL_PROCESS_BIND: case SVM_IOCTL_PROCESS_BIND:
return "bind"; return "bind";
case SVM_IOCTL_REMAP_PROC:
return "remap proc";
case SVM_IOCTL_LOAD_FLAG: case SVM_IOCTL_LOAD_FLAG:
return "load flag"; return "load flag";
case SVM_IOCTL_RELEASE_PHYS32: case SVM_IOCTL_RELEASE_PHYS32:
...@@ -497,6 +509,151 @@ static int svm_open(struct inode *inode, struct file *file) ...@@ -497,6 +509,151 @@ static int svm_open(struct inode *inode, struct file *file)
return 0; return 0;
} }
static long svm_remap_get_phys(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long addr, unsigned long *phys,
unsigned long *page_size, unsigned long *offset)
{
long err = -EINVAL;
pgd_t *pgd = NULL;
p4d_t *p4d = NULL;
pud_t *pud = NULL;
pte_t *pte = NULL;
if (mm == NULL || vma == NULL || phys == NULL ||
page_size == NULL || offset == NULL)
return err;
pgd = pgd_offset(mm, addr);
if (pgd_none_or_clear_bad(pgd))
return err;
p4d = p4d_offset(pgd, addr);
if (p4d_none_or_clear_bad(p4d))
return err;
pud = pud_offset(p4d, addr);
if (pud_none_or_clear_bad(pud))
return err;
pte = svm_get_pte(vma, pud, addr, page_size, offset);
if (pte && pte_present(*pte)) {
*phys = PFN_PHYS(pte_pfn(*pte));
return 0;
}
return err;
}
static long svm_remap_proc(unsigned long __user *arg)
{
long ret = -EINVAL;
struct svm_proc_mem pmem;
struct task_struct *ptask = NULL;
struct mm_struct *pmm = NULL, *mm = current->mm;
struct vm_area_struct *pvma = NULL, *vma = NULL;
unsigned long end, vaddr, phys, buf, offset, pagesize;
if (!acpi_disabled)
return -EPERM;
if (arg == NULL) {
pr_err("arg is invalid.\n");
return ret;
}
ret = copy_from_user(&pmem, (void __user *)arg, sizeof(pmem));
if (ret) {
pr_err("failed to copy args from user space.\n");
return -EFAULT;
}
if (pmem.buf & (PAGE_SIZE - 1)) {
pr_err("address is not aligned with page size, addr:%pK.\n",
(void *)pmem.buf);
return -EINVAL;
}
rcu_read_lock();
if (pmem.pid) {
ptask = find_task_by_vpid(pmem.pid);
if (!ptask) {
rcu_read_unlock();
pr_err("No task for this pid\n");
return -EINVAL;
}
} else {
ptask = current;
}
get_task_struct(ptask);
rcu_read_unlock();
pmm = ptask->mm;
down_read(&mm->mmap_lock);
down_read(&pmm->mmap_lock);
pvma = find_vma(pmm, pmem.vaddr);
if (pvma == NULL) {
ret = -ESRCH;
goto err;
}
vma = find_vma(mm, pmem.buf);
if (vma == NULL) {
ret = -ESRCH;
goto err;
}
if (pmem.len > SVM_REMAP_MEM_LEN_MAX) {
ret = -EINVAL;
pr_err("too large length of memory.\n");
goto err;
}
vaddr = pmem.vaddr;
end = vaddr + pmem.len;
buf = pmem.buf;
vma->vm_flags |= VM_SHARED;
if (end > pvma->vm_end || end < vaddr) {
ret = -EINVAL;
pr_err("memory length is out of range, vaddr:%pK, len:%u.\n",
(void *)vaddr, pmem.len);
goto err;
}
do {
ret = svm_remap_get_phys(pmm, pvma, vaddr,
&phys, &pagesize, &offset);
if (ret) {
ret = -EINVAL;
goto err;
}
vaddr += pagesize - offset;
do {
if (remap_pfn_range(vma, buf, phys >> PAGE_SHIFT,
PAGE_SIZE,
__pgprot(vma->vm_page_prot.pgprot |
PTE_DIRTY))) {
ret = -ESRCH;
goto err;
}
offset += PAGE_SIZE;
buf += PAGE_SIZE;
phys += PAGE_SIZE;
} while (offset < pagesize);
} while (vaddr < end);
err:
up_read(&pmm->mmap_lock);
up_read(&mm->mmap_lock);
put_task_struct(ptask);
return ret;
}
static int svm_proc_load_flag(int __user *arg) static int svm_proc_load_flag(int __user *arg)
{ {
static atomic_t l2buf_load_flag = ATOMIC_INIT(0); static atomic_t l2buf_load_flag = ATOMIC_INIT(0);
...@@ -711,6 +868,9 @@ static long svm_ioctl(struct file *file, unsigned int cmd, ...@@ -711,6 +868,9 @@ static long svm_ioctl(struct file *file, unsigned int cmd,
return -EFAULT; return -EFAULT;
} }
break; break;
case SVM_IOCTL_REMAP_PROC:
err = svm_remap_proc((unsigned long __user *)arg);
break;
case SVM_IOCTL_LOAD_FLAG: case SVM_IOCTL_LOAD_FLAG:
err = svm_proc_load_flag((int __user *)arg); err = svm_proc_load_flag((int __user *)arg);
break; break;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册