Blame view

mm/gup_benchmark.c 2.8 KB
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
1
2
3
4
5
6
7
8
  #include <linux/kernel.h>
  #include <linux/mm.h>
  #include <linux/slab.h>
  #include <linux/uaccess.h>
  #include <linux/ktime.h>
  #include <linux/debugfs.h>
  
  #define GUP_FAST_BENCHMARK	_IOWR('g', 1, struct gup_benchmark)
714a3a1eb   Keith Busch   mm/gup_benchmark....
9
10
  #define GUP_LONGTERM_BENCHMARK	_IOWR('g', 2, struct gup_benchmark)
  #define GUP_BENCHMARK		_IOWR('g', 3, struct gup_benchmark)
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
11
12
  
  struct gup_benchmark {
26db3d09d   Keith Busch   mm/gup_benchmark....
13
14
  	__u64 get_delta_usec;
  	__u64 put_delta_usec;
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
15
16
17
18
  	__u64 addr;
  	__u64 size;
  	__u32 nr_pages_per_call;
  	__u32 flags;
26db3d09d   Keith Busch   mm/gup_benchmark....
19
  	__u64 expansion[10];	/* For future use */
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
20
21
22
23
24
25
  };
  
  static int __gup_benchmark_ioctl(unsigned int cmd,
  		struct gup_benchmark *gup)
  {
  	ktime_t start_time, end_time;
518968645   YueHaibing   mm/gup_benchmark:...
26
27
  	unsigned long i, nr_pages, addr, next;
  	int nr;
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
28
  	struct page **pages;
20170bfa3   Navid Emamdoost   mm/gup: fix memor...
29
  	int ret = 0;
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
30

4b408c74e   Dan Carpenter   mm/gup_benchmark....
31
32
  	if (gup->size > ULONG_MAX)
  		return -EINVAL;
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
33
  	nr_pages = gup->size / PAGE_SIZE;
778e1cdd8   Kees Cook   treewide: kvzallo...
34
  	pages = kvcalloc(nr_pages, sizeof(void *), GFP_KERNEL);
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  	if (!pages)
  		return -ENOMEM;
  
  	i = 0;
  	nr = gup->nr_pages_per_call;
  	start_time = ktime_get();
  	for (addr = gup->addr; addr < gup->addr + gup->size; addr = next) {
  		if (nr != gup->nr_pages_per_call)
  			break;
  
  		next = addr + nr * PAGE_SIZE;
  		if (next > gup->addr + gup->size) {
  			next = gup->addr + gup->size;
  			nr = (next - addr) / PAGE_SIZE;
  		}
714a3a1eb   Keith Busch   mm/gup_benchmark....
50
51
52
53
54
55
  		switch (cmd) {
  		case GUP_FAST_BENCHMARK:
  			nr = get_user_pages_fast(addr, nr, gup->flags & 1,
  						 pages + i);
  			break;
  		case GUP_LONGTERM_BENCHMARK:
932f4a630   Ira Weiny   mm/gup: replace g...
56
57
58
  			nr = get_user_pages(addr, nr,
  					    (gup->flags & 1) | FOLL_LONGTERM,
  					    pages + i, NULL);
714a3a1eb   Keith Busch   mm/gup_benchmark....
59
60
61
62
63
64
  			break;
  		case GUP_BENCHMARK:
  			nr = get_user_pages(addr, nr, gup->flags & 1, pages + i,
  					    NULL);
  			break;
  		default:
20170bfa3   Navid Emamdoost   mm/gup: fix memor...
65
66
67
  			kvfree(pages);
  			ret = -EINVAL;
  			goto out;
714a3a1eb   Keith Busch   mm/gup_benchmark....
68
  		}
09e35a4a1   Michael S. Tsirkin   mm/gup_benchmark:...
69
70
  		if (nr <= 0)
  			break;
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
71
72
73
  		i += nr;
  	}
  	end_time = ktime_get();
26db3d09d   Keith Busch   mm/gup_benchmark....
74
  	gup->get_delta_usec = ktime_us_delta(end_time, start_time);
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
75
  	gup->size = addr - gup->addr;
26db3d09d   Keith Busch   mm/gup_benchmark....
76
  	start_time = ktime_get();
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
77
78
79
80
81
  	for (i = 0; i < nr_pages; i++) {
  		if (!pages[i])
  			break;
  		put_page(pages[i]);
  	}
26db3d09d   Keith Busch   mm/gup_benchmark....
82
83
  	end_time = ktime_get();
  	gup->put_delta_usec = ktime_us_delta(end_time, start_time);
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
84
85
  
  	kvfree(pages);
20170bfa3   Navid Emamdoost   mm/gup: fix memor...
86
87
  out:
  	return ret;
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
88
89
90
91
92
93
94
  }
  
  static long gup_benchmark_ioctl(struct file *filep, unsigned int cmd,
  		unsigned long arg)
  {
  	struct gup_benchmark gup;
  	int ret;
714a3a1eb   Keith Busch   mm/gup_benchmark....
95
96
97
98
99
100
  	switch (cmd) {
  	case GUP_FAST_BENCHMARK:
  	case GUP_LONGTERM_BENCHMARK:
  	case GUP_BENCHMARK:
  		break;
  	default:
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
101
  		return -EINVAL;
714a3a1eb   Keith Busch   mm/gup_benchmark....
102
  	}
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  
  	if (copy_from_user(&gup, (void __user *)arg, sizeof(gup)))
  		return -EFAULT;
  
  	ret = __gup_benchmark_ioctl(cmd, &gup);
  	if (ret)
  		return ret;
  
  	if (copy_to_user((void __user *)arg, &gup, sizeof(gup)))
  		return -EFAULT;
  
  	return 0;
  }
  
  static const struct file_operations gup_benchmark_fops = {
  	.open = nonseekable_open,
  	.unlocked_ioctl = gup_benchmark_ioctl,
  };
  
  static int gup_benchmark_init(void)
  {
d9f7979c9   Greg Kroah-Hartman   mm: no need to ch...
124
125
  	debugfs_create_file_unsafe("gup_benchmark", 0600, NULL, NULL,
  				   &gup_benchmark_fops);
64c349f4a   Kirill A. Shutemov   mm: add infrastru...
126
127
128
129
130
  
  	return 0;
  }
  
  late_initcall(gup_benchmark_init);