linux/kernel/power/user.c
<<
>>
Prefs
   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 - pg_offp;
 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);
 452