/* * swsusp.h * * Common definitions for user space suspend and resume handlers. * * Copyright (C) 2005 Rafael J. Wysocki * * This file is released under the GPLv2. * */ #define PAGE_SIZE 4096 #define SNAPSHOT_IOC_MAGIC '3' #define SNAPSHOT_IOCFREEZE _IO(SNAPSHOT_IOC_MAGIC, 1) #define SNAPSHOT_IOCUNFREEZE _IO(SNAPSHOT_IOC_MAGIC, 2) #define SNAPSHOT_IOCATOMIC_SNAPSHOT _IOW(SNAPSHOT_IOC_MAGIC, 3, void *) #define SNAPSHOT_IOCATOMIC_RESTORE _IO(SNAPSHOT_IOC_MAGIC, 4) #define SNAPSHOT_IOCSET_IMAGE_SIZE _IOW(SNAPSHOT_IOC_MAGIC, 5, unsigned long) #define SNAPSHOT_IOCAVAIL_SWAP _IOR(SNAPSHOT_IOC_MAGIC, 6, void *) #define SNAPSHOT_IOCGET_SWAP_PAGE _IOR(SNAPSHOT_IOC_MAGIC, 7, void *) #define SNAPSHOT_IOCFREE_SWAP_PAGE _IOW(SNAPSHOT_IOC_MAGIC, 8, unsigned long) #define SNAPSHOT_IOC_MAXNR 8 #define LINUX_REBOOT_MAGIC1 0xfee1dead #define LINUX_REBOOT_MAGIC2 672274793 #define LINUX_REBOOT_CMD_RESTART 0x01234567 #define LINUX_REBOOT_CMD_HALT 0xCDEF0123 #define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC #define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4 #define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2 struct new_utsname { char sysname[65]; char nodename[65]; char release[65]; char version[65]; char machine[65]; char domainname[65]; }; struct swsusp_info { struct new_utsname uts; unsigned int version_code; unsigned long num_physpages; int cpus; unsigned long image_pages; unsigned long pages; } __attribute__((aligned(PAGE_SIZE))); #define SWSUSP_SIG "S1SUSPEND" static struct swsusp_header { char reserved[PAGE_SIZE - 20 - sizeof(long)]; unsigned long image; char orig_sig[10]; char sig[10]; } __attribute__((packed, aligned(PAGE_SIZE))) swsusp_header; static inline int freeze(int dev) { return ioctl(dev, SNAPSHOT_IOCFREEZE, 0); } static inline int unfreeze(int dev) { return ioctl(dev, SNAPSHOT_IOCUNFREEZE, 0); } static inline int atomic_snapshot(int dev, int *in_suspend) { return ioctl(dev, SNAPSHOT_IOCATOMIC_SNAPSHOT, in_suspend); } static inline int atomic_restore(int dev) { return ioctl(dev, SNAPSHOT_IOCATOMIC_RESTORE, 0); } static inline int set_image_size(int dev, unsigned int size) { return ioctl(dev, SNAPSHOT_IOCSET_IMAGE_SIZE, size); } static inline void reboot(void) { syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART, 0); } static inline void power_off(void) { syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, 0); } /* * The swap map is a data structure used for keeping track of each page * written to the swap. It consists of many swap_map_page structures * that contain each an array of MAP_PAGE_SIZE swap entries. * These structures are linked together with the help of either the * .next (in memory) or the .next_swap (in swap) member. * * The swap map is created during suspend. At that time we need to keep * it in memory, because we have to free all of the allocated swap * entries if an error occurs. The memory needed is preallocated * so that we know in advance if there's enough of it. * * The first swap_map_page structure is filled with the swap entries that * correspond to the first MAP_PAGE_SIZE data pages written to swap and * so on. After the all of the data pages have been written, the order * of the swap_map_page structures in the map is reversed so that they * can be read from swap in the original order. This causes the data * pages to be loaded in exactly the same order in which they have been * saved. * * During resume we only need to use one swap_map_page structure * at a time, which means that we only need to use two memory pages for * reading the image - one for reading the swap_map_page structures * and the second for reading the data pages from swap. */ #define MAP_PAGE_SIZE ((PAGE_SIZE - sizeof(long) - sizeof(void *)) \ / sizeof(long)) struct swap_map_page { unsigned long entries[MAP_PAGE_SIZE]; unsigned long next_swap; struct swap_map_page *next; }; /* * The swap_map_handle structure is used for handling the swap map in * a file-alike way */ struct swap_map_handle { struct swap_map_page *cur; unsigned int k; int fd; }; #define SNAPSHOT_DEVICE "/dev/snapshot" #define RESUME_DEVICE "/dev/hdc3" #define DEFAULT_IMAGE_SIZE 500