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