mm: split swap_type_of
[platform/kernel/linux-starfive.git] / kernel / power / user.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * linux/kernel/power/user.c
4  *
5  * This file provides the user space interface for software suspend/resume.
6  *
7  * Copyright (C) 2006 Rafael J. Wysocki <rjw@sisk.pl>
8  */
9
10 #include <linux/suspend.h>
11 #include <linux/reboot.h>
12 #include <linux/string.h>
13 #include <linux/device.h>
14 #include <linux/miscdevice.h>
15 #include <linux/mm.h>
16 #include <linux/swap.h>
17 #include <linux/swapops.h>
18 #include <linux/pm.h>
19 #include <linux/fs.h>
20 #include <linux/compat.h>
21 #include <linux/console.h>
22 #include <linux/cpu.h>
23 #include <linux/freezer.h>
24
25 #include <linux/uaccess.h>
26
27 #include "power.h"
28
29
30 static struct snapshot_data {
31         struct snapshot_handle handle;
32         int swap;
33         int mode;
34         bool frozen;
35         bool ready;
36         bool platform_support;
37         bool free_bitmaps;
38         dev_t dev;
39 } snapshot_state;
40
41 int is_hibernate_resume_dev(dev_t dev)
42 {
43         return hibernation_available() && snapshot_state.dev == dev;
44 }
45
46 static int snapshot_open(struct inode *inode, struct file *filp)
47 {
48         struct snapshot_data *data;
49         int error, nr_calls = 0;
50
51         if (!hibernation_available())
52                 return -EPERM;
53
54         lock_system_sleep();
55
56         if (!hibernate_acquire()) {
57                 error = -EBUSY;
58                 goto Unlock;
59         }
60
61         if ((filp->f_flags & O_ACCMODE) == O_RDWR) {
62                 hibernate_release();
63                 error = -ENOSYS;
64                 goto Unlock;
65         }
66         nonseekable_open(inode, filp);
67         data = &snapshot_state;
68         filp->private_data = data;
69         memset(&data->handle, 0, sizeof(struct snapshot_handle));
70         if ((filp->f_flags & O_ACCMODE) == O_RDONLY) {
71                 /* Hibernating.  The image device should be accessible. */
72                 data->swap = swap_type_of(swsusp_resume_device, 0);
73                 data->mode = O_RDONLY;
74                 data->free_bitmaps = false;
75                 error = __pm_notifier_call_chain(PM_HIBERNATION_PREPARE, -1, &nr_calls);
76                 if (error)
77                         __pm_notifier_call_chain(PM_POST_HIBERNATION, --nr_calls, NULL);
78         } else {
79                 /*
80                  * Resuming.  We may need to wait for the image device to
81                  * appear.
82                  */
83                 wait_for_device_probe();
84
85                 data->swap = -1;
86                 data->mode = O_WRONLY;
87                 error = __pm_notifier_call_chain(PM_RESTORE_PREPARE, -1, &nr_calls);
88                 if (!error) {
89                         error = create_basic_memory_bitmaps();
90                         data->free_bitmaps = !error;
91                 } else
92                         nr_calls--;
93
94                 if (error)
95                         __pm_notifier_call_chain(PM_POST_RESTORE, nr_calls, NULL);
96         }
97         if (error)
98                 hibernate_release();
99
100         data->frozen = false;
101         data->ready = false;
102         data->platform_support = false;
103         data->dev = 0;
104
105  Unlock:
106         unlock_system_sleep();
107
108         return error;
109 }
110
111 static int snapshot_release(struct inode *inode, struct file *filp)
112 {
113         struct snapshot_data *data;
114
115         lock_system_sleep();
116
117         swsusp_free();
118         data = filp->private_data;
119         data->dev = 0;
120         free_all_swap_pages(data->swap);
121         if (data->frozen) {
122                 pm_restore_gfp_mask();
123                 free_basic_memory_bitmaps();
124                 thaw_processes();
125         } else if (data->free_bitmaps) {
126                 free_basic_memory_bitmaps();
127         }
128         pm_notifier_call_chain(data->mode == O_RDONLY ?
129                         PM_POST_HIBERNATION : PM_POST_RESTORE);
130         hibernate_release();
131
132         unlock_system_sleep();
133
134         return 0;
135 }
136
137 static ssize_t snapshot_read(struct file *filp, char __user *buf,
138                              size_t count, loff_t *offp)
139 {
140         struct snapshot_data *data;
141         ssize_t res;
142         loff_t pg_offp = *offp & ~PAGE_MASK;
143
144         lock_system_sleep();
145
146         data = filp->private_data;
147         if (!data->ready) {
148                 res = -ENODATA;
149                 goto Unlock;
150         }
151         if (!pg_offp) { /* on page boundary? */
152                 res = snapshot_read_next(&data->handle);
153                 if (res <= 0)
154                         goto Unlock;
155         } else {
156                 res = PAGE_SIZE - pg_offp;
157         }
158
159         res = simple_read_from_buffer(buf, count, &pg_offp,
160                         data_of(data->handle), res);
161         if (res > 0)
162                 *offp += res;
163
164  Unlock:
165         unlock_system_sleep();
166
167         return res;
168 }
169
170 static ssize_t snapshot_write(struct file *filp, const char __user *buf,
171                               size_t count, loff_t *offp)
172 {
173         struct snapshot_data *data;
174         ssize_t res;
175         loff_t pg_offp = *offp & ~PAGE_MASK;
176
177         lock_system_sleep();
178
179         data = filp->private_data;
180
181         if (!pg_offp) {
182                 res = snapshot_write_next(&data->handle);
183                 if (res <= 0)
184                         goto unlock;
185         } else {
186                 res = PAGE_SIZE - pg_offp;
187         }
188
189         if (!data_of(data->handle)) {
190                 res = -EINVAL;
191                 goto unlock;
192         }
193
194         res = simple_write_to_buffer(data_of(data->handle), res, &pg_offp,
195                         buf, count);
196         if (res > 0)
197                 *offp += res;
198 unlock:
199         unlock_system_sleep();
200
201         return res;
202 }
203
204 struct compat_resume_swap_area {
205         compat_loff_t offset;
206         u32 dev;
207 } __packed;
208
209 static int snapshot_set_swap_area(struct snapshot_data *data,
210                 void __user *argp)
211 {
212         sector_t offset;
213         dev_t swdev;
214
215         if (swsusp_swap_in_use())
216                 return -EPERM;
217
218         if (in_compat_syscall()) {
219                 struct compat_resume_swap_area swap_area;
220
221                 if (copy_from_user(&swap_area, argp, sizeof(swap_area)))
222                         return -EFAULT;
223                 swdev = new_decode_dev(swap_area.dev);
224                 offset = swap_area.offset;
225         } else {
226                 struct resume_swap_area swap_area;
227
228                 if (copy_from_user(&swap_area, argp, sizeof(swap_area)))
229                         return -EFAULT;
230                 swdev = new_decode_dev(swap_area.dev);
231                 offset = swap_area.offset;
232         }
233
234         /*
235          * User space encodes device types as two-byte values,
236          * so we need to recode them
237          */
238         data->swap = swap_type_of(swdev, offset);
239         if (data->swap < 0)
240                 return swdev ? -ENODEV : -EINVAL;
241         data->dev = swdev;
242         return 0;
243 }
244
245 static long snapshot_ioctl(struct file *filp, unsigned int cmd,
246                                                         unsigned long arg)
247 {
248         int error = 0;
249         struct snapshot_data *data;
250         loff_t size;
251         sector_t offset;
252
253         if (_IOC_TYPE(cmd) != SNAPSHOT_IOC_MAGIC)
254                 return -ENOTTY;
255         if (_IOC_NR(cmd) > SNAPSHOT_IOC_MAXNR)
256                 return -ENOTTY;
257         if (!capable(CAP_SYS_ADMIN))
258                 return -EPERM;
259
260         if (!mutex_trylock(&system_transition_mutex))
261                 return -EBUSY;
262
263         lock_device_hotplug();
264         data = filp->private_data;
265
266         switch (cmd) {
267
268         case SNAPSHOT_FREEZE:
269                 if (data->frozen)
270                         break;
271
272                 ksys_sync_helper();
273
274                 error = freeze_processes();
275                 if (error)
276                         break;
277
278                 error = create_basic_memory_bitmaps();
279                 if (error)
280                         thaw_processes();
281                 else
282                         data->frozen = true;
283
284                 break;
285
286         case SNAPSHOT_UNFREEZE:
287                 if (!data->frozen || data->ready)
288                         break;
289                 pm_restore_gfp_mask();
290                 free_basic_memory_bitmaps();
291                 data->free_bitmaps = false;
292                 thaw_processes();
293                 data->frozen = false;
294                 break;
295
296         case SNAPSHOT_CREATE_IMAGE:
297                 if (data->mode != O_RDONLY || !data->frozen  || data->ready) {
298                         error = -EPERM;
299                         break;
300                 }
301                 pm_restore_gfp_mask();
302                 error = hibernation_snapshot(data->platform_support);
303                 if (!error) {
304                         error = put_user(in_suspend, (int __user *)arg);
305                         data->ready = !freezer_test_done && !error;
306                         freezer_test_done = false;
307                 }
308                 break;
309
310         case SNAPSHOT_ATOMIC_RESTORE:
311                 snapshot_write_finalize(&data->handle);
312                 if (data->mode != O_WRONLY || !data->frozen ||
313                     !snapshot_image_loaded(&data->handle)) {
314                         error = -EPERM;
315                         break;
316                 }
317                 error = hibernation_restore(data->platform_support);
318                 break;
319
320         case SNAPSHOT_FREE:
321                 swsusp_free();
322                 memset(&data->handle, 0, sizeof(struct snapshot_handle));
323                 data->ready = false;
324                 /*
325                  * It is necessary to thaw kernel threads here, because
326                  * SNAPSHOT_CREATE_IMAGE may be invoked directly after
327                  * SNAPSHOT_FREE.  In that case, if kernel threads were not
328                  * thawed, the preallocation of memory carried out by
329                  * hibernation_snapshot() might run into problems (i.e. it
330                  * might fail or even deadlock).
331                  */
332                 thaw_kernel_threads();
333                 break;
334
335         case SNAPSHOT_PREF_IMAGE_SIZE:
336                 image_size = arg;
337                 break;
338
339         case SNAPSHOT_GET_IMAGE_SIZE:
340                 if (!data->ready) {
341                         error = -ENODATA;
342                         break;
343                 }
344                 size = snapshot_get_image_size();
345                 size <<= PAGE_SHIFT;
346                 error = put_user(size, (loff_t __user *)arg);
347                 break;
348
349         case SNAPSHOT_AVAIL_SWAP_SIZE:
350                 size = count_swap_pages(data->swap, 1);
351                 size <<= PAGE_SHIFT;
352                 error = put_user(size, (loff_t __user *)arg);
353                 break;
354
355         case SNAPSHOT_ALLOC_SWAP_PAGE:
356                 if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
357                         error = -ENODEV;
358                         break;
359                 }
360                 offset = alloc_swapdev_block(data->swap);
361                 if (offset) {
362                         offset <<= PAGE_SHIFT;
363                         error = put_user(offset, (loff_t __user *)arg);
364                 } else {
365                         error = -ENOSPC;
366                 }
367                 break;
368
369         case SNAPSHOT_FREE_SWAP_PAGES:
370                 if (data->swap < 0 || data->swap >= MAX_SWAPFILES) {
371                         error = -ENODEV;
372                         break;
373                 }
374                 free_all_swap_pages(data->swap);
375                 break;
376
377         case SNAPSHOT_S2RAM:
378                 if (!data->frozen) {
379                         error = -EPERM;
380                         break;
381                 }
382                 /*
383                  * Tasks are frozen and the notifiers have been called with
384                  * PM_HIBERNATION_PREPARE
385                  */
386                 error = suspend_devices_and_enter(PM_SUSPEND_MEM);
387                 data->ready = false;
388                 break;
389
390         case SNAPSHOT_PLATFORM_SUPPORT:
391                 data->platform_support = !!arg;
392                 break;
393
394         case SNAPSHOT_POWER_OFF:
395                 if (data->platform_support)
396                         error = hibernation_platform_enter();
397                 break;
398
399         case SNAPSHOT_SET_SWAP_AREA:
400                 error = snapshot_set_swap_area(data, (void __user *)arg);
401                 break;
402
403         default:
404                 error = -ENOTTY;
405
406         }
407
408         unlock_device_hotplug();
409         mutex_unlock(&system_transition_mutex);
410
411         return error;
412 }
413
414 #ifdef CONFIG_COMPAT
415 static long
416 snapshot_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
417 {
418         BUILD_BUG_ON(sizeof(loff_t) != sizeof(compat_loff_t));
419
420         switch (cmd) {
421         case SNAPSHOT_GET_IMAGE_SIZE:
422         case SNAPSHOT_AVAIL_SWAP_SIZE:
423         case SNAPSHOT_ALLOC_SWAP_PAGE:
424         case SNAPSHOT_CREATE_IMAGE:
425         case SNAPSHOT_SET_SWAP_AREA:
426                 return snapshot_ioctl(file, cmd,
427                                       (unsigned long) compat_ptr(arg));
428         default:
429                 return snapshot_ioctl(file, cmd, arg);
430         }
431 }
432 #endif /* CONFIG_COMPAT */
433
434 static const struct file_operations snapshot_fops = {
435         .open = snapshot_open,
436         .release = snapshot_release,
437         .read = snapshot_read,
438         .write = snapshot_write,
439         .llseek = no_llseek,
440         .unlocked_ioctl = snapshot_ioctl,
441 #ifdef CONFIG_COMPAT
442         .compat_ioctl = snapshot_compat_ioctl,
443 #endif
444 };
445
446 static struct miscdevice snapshot_device = {
447         .minor = SNAPSHOT_MINOR,
448         .name = "snapshot",
449         .fops = &snapshot_fops,
450 };
451
452 static int __init snapshot_device_init(void)
453 {
454         return misc_register(&snapshot_device);
455 };
456
457 device_initcall(snapshot_device_init);