forked from pengdonglin137/remap_pfn_demo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
remap_pfn_alloc_pages.c
92 lines (74 loc) · 2.37 KB
/
remap_pfn_alloc_pages.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include <linux/slab.h>
#define BUF_SIZE (32*PAGE_SIZE)
static struct page *start_page;
static int remap_pfn_open(struct inode *inode, struct file *file)
{
struct mm_struct *mm = current->mm;
printk("client: %s (%d)\n", current->comm, current->pid);
printk("code section: [0x%lx 0x%lx]\n", mm->start_code, mm->end_code);
printk("data section: [0x%lx 0x%lx]\n", mm->start_data, mm->end_data);
printk("brk section: s: 0x%lx, c: 0x%lx\n", mm->start_brk, mm->brk);
printk("mmap section: s: 0x%lx\n", mm->mmap_base);
printk("stack section: s: 0x%lx\n", mm->start_stack);
printk("arg section: [0x%lx 0x%lx]\n", mm->arg_start, mm->arg_end);
printk("env section: [0x%lx 0x%lx]\n", mm->env_start, mm->env_end);
return 0;
}
static int remap_pfn_mmap(struct file *file, struct vm_area_struct *vma)
{
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
unsigned long pfn_start = page_to_pfn(start_page) + vma->vm_pgoff;
unsigned long virt_start = (unsigned long)page_address(start_page);
unsigned long size = vma->vm_end - vma->vm_start;
int ret = 0;
printk("phy: 0x%lx, offset: 0x%lx, size: 0x%lx\n", pfn_start << PAGE_SHIFT, offset, size);
ret = remap_pfn_range(vma, vma->vm_start, pfn_start, size, vma->vm_page_prot);
if (ret)
printk("%s: remap_pfn_range failed at [0x%lx 0x%lx]\n",
__func__, vma->vm_start, vma->vm_end);
else
printk("%s: map 0x%lx to 0x%lx, size: 0x%lx\n", __func__, virt_start,
vma->vm_start, size);
return ret;
}
static const struct file_operations remap_pfn_fops = {
.owner = THIS_MODULE,
.open = remap_pfn_open,
.mmap = remap_pfn_mmap,
};
static struct miscdevice remap_pfn_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "remap_pfn",
.fops = &remap_pfn_fops,
};
static int __init remap_pfn_init(void)
{
int ret = 0;
start_page = alloc_pages(GFP_KERNEL, get_order(BUF_SIZE));
if (!start_page) {
ret = -ENOMEM;
goto err;
}
ret = misc_register(&remap_pfn_misc);
if (unlikely(ret)) {
pr_err("failed to register misc device!\n");
goto err;
}
return 0;
err:
return ret;
}
static void __exit remap_pfn_exit(void)
{
misc_deregister(&remap_pfn_misc);
__free_pages(start_page, get_order(BUF_SIZE));
}
module_init(remap_pfn_init);
module_exit(remap_pfn_exit);
MODULE_LICENSE("GPL");