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