Commit 7c548885 authored by Pavel Machek's avatar Pavel Machek Committed by Linus Torvalds

[PATCH] swsusp: 64-bit compatibility

This makes swsusp 64bit compatible, and makes it work in case of two
mirrors of physical memory (x86-64 works like that). It also contains
few accumulated cleanups.
parent ba95d79a
......@@ -80,9 +80,9 @@ unsigned char software_suspend_enabled = 0;
#endif
#define TIMEOUT (6 * HZ) /* Timeout for stopping processes */
#define ADDRESS(x) ((unsigned long) phys_to_virt(((x) << PAGE_SHIFT)))
extern int C_A_D;
#define __ADDRESS(x) ((unsigned long) phys_to_virt(x))
#define ADDRESS(x) __ADDRESS((x) << PAGE_SHIFT)
#define ADDRESS2(x) __ADDRESS(__pa(x)) /* Needed for x86-64 where some pages are in memory twice */
/* References to section boundaries */
extern char _text, _etext, _edata, __bss_start, _end;
......@@ -145,10 +145,10 @@ static const char name_resume[] = "Resume Machine: ";
/*
* Debug
*/
#undef DEBUG_DEFAULT
#define DEBUG_DEFAULT
#undef DEBUG_PROCESS
#undef DEBUG_SLOW
#define TEST_SWSUSP 1 /* Set to 1 to reboot instead of halt machine after suspension */
#define TEST_SWSUSP 0 /* Set to 1 to reboot instead of halt machine after suspension */
#ifdef DEBUG_DEFAULT
# define PRINTK(f, a...) printk(f, ## a)
......@@ -235,6 +235,7 @@ int freeze_processes(void)
} while(todo);
printk( "|\n" );
BUG_ON(in_atomic());
return 0;
}
......@@ -322,20 +323,20 @@ static void mark_swapfiles(swp_entry_t prev, int mode)
rw_swap_page_sync(READ, entry, page);
if (mode == MARK_SWAP_RESUME) {
if (!memcmp("SUSP1R",cur->swh.magic.magic,6))
if (!memcmp("S1",cur->swh.magic.magic,2))
memcpy(cur->swh.magic.magic,"SWAP-SPACE",10);
else if (!memcmp("SUSP2R",cur->swh.magic.magic,6))
else if (!memcmp("S2",cur->swh.magic.magic,2))
memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
else printk("%sUnable to find suspended-data signature (%.10s - misspelled?\n",
name_resume, cur->swh.magic.magic);
} else {
if ((!memcmp("SWAP-SPACE",cur->swh.magic.magic,10)))
memcpy(cur->swh.magic.magic,"SUSP1R....",10);
memcpy(cur->swh.magic.magic,"S1SUSP....",10);
else if ((!memcmp("SWAPSPACE2",cur->swh.magic.magic,10)))
memcpy(cur->swh.magic.magic,"SUSP2R....",10);
memcpy(cur->swh.magic.magic,"S2SUSP....",10);
else panic("\nSwapspace is not swapspace (%.10s)\n", cur->swh.magic.magic);
cur->link.next = prev; /* prev is the first/last swap page of the resume area */
/* link.next lies *no more* in last 4 bytes of magic */
/* link.next lies *no more* in last 4/8 bytes of magic */
}
rw_swap_page_sync(WRITE, entry, page);
__free_page(page);
......@@ -489,7 +490,6 @@ static int count_and_copy_data_pages(struct pbe *pagedir_p)
if (PageNosave(page))
continue;
if ((chunk_size=is_head_of_free_region(page))!=0) {
pfn += chunk_size - 1;
continue;
......@@ -500,10 +500,9 @@ static int count_and_copy_data_pages(struct pbe *pagedir_p)
/*
* Just copy whole code segment. Hopefully it is not that big.
*/
if (ADDRESS(pfn) >= (unsigned long)
&__nosave_begin && ADDRESS(pfn) <
(unsigned long)&__nosave_end) {
PRINTK("[nosave %x]", ADDRESS(pfn));
if ((ADDRESS(pfn) >= (unsigned long) ADDRESS2(&__nosave_begin)) &&
(ADDRESS(pfn) < (unsigned long) ADDRESS2(&__nosave_end))) {
PRINTK("[nosave %lx]", ADDRESS(pfn));
continue;
}
/* Hmm, perhaps copying all reserved pages is not too healthy as they may contain
......@@ -513,7 +512,7 @@ static int count_and_copy_data_pages(struct pbe *pagedir_p)
nr_copy_pages++;
if (pagedir_p) {
pagedir_p->orig_address = ADDRESS(pfn);
copy_page(pagedir_p->address, pagedir_p->orig_address);
copy_page((void *) pagedir_p->address, (void *) pagedir_p->orig_address);
pagedir_p++;
}
}
......@@ -549,7 +548,7 @@ static suspend_pagedir_t *create_suspend_pagedir(int nr_copy_pages)
pagedir_order = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages));
p = pagedir = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC, pagedir_order);
p = pagedir = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD, pagedir_order);
if(!pagedir)
return NULL;
......@@ -558,11 +557,12 @@ static suspend_pagedir_t *create_suspend_pagedir(int nr_copy_pages)
SetPageNosave(page++);
while(nr_copy_pages--) {
p->address = get_zeroed_page(GFP_ATOMIC);
p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
if(!p->address) {
free_suspend_pagedir((unsigned long) pagedir);
return NULL;
}
printk(".");
SetPageNosave(virt_to_page(p->address));
p->orig_address = 0;
p++;
......@@ -623,7 +623,7 @@ static int prepare_suspend_processes(void)
static void free_some_memory(void)
{
printk("Freeing memory: ");
while (try_to_free_pages(&contig_page_data.node_zones[ZONE_HIGHMEM], GFP_KSWAPD, 0))
while (shrink_all_memory(10000))
printk(".");
printk("|\n");
}
......@@ -676,7 +676,7 @@ static void drivers_resume(int flags)
}
}
static int suspend_save_image(void)
static int suspend_prepare_image(void)
{
struct sysinfo i;
unsigned int nr_needed_pages = 0;
......@@ -725,9 +725,15 @@ static int suspend_save_image(void)
*
* Following line enforces not writing to disk until we choose.
*/
drivers_unsuspend();
spin_unlock_irq(&suspend_pagedir_lock);
printk( "critical section/: done (%d pages copied)\n", nr_copy_pages );
spin_unlock_irq(&suspend_pagedir_lock);
return 0;
}
static void suspend_save_image(void)
{
drivers_unsuspend();
lock_swapdevices();
write_suspend_image();
......@@ -738,11 +744,11 @@ static int suspend_save_image(void)
* filesystem clean: it is not. (And it does not matter, if we resume
* correctly, we'll mark system clean, anyway.)
*/
return 0;
}
void suspend_power_down(void)
static void suspend_power_down(void)
{
extern int C_A_D;
C_A_D = 0;
printk(KERN_EMERG "%s%s Trying to power down.\n", name_suspend, TEST_SWSUSP ? "Disable TEST_SWSUSP. NOT ": "");
#ifdef CONFIG_VT
......@@ -788,8 +794,8 @@ void do_magic_resume_2(void)
PRINTK( "Freeing prev allocated pagedir\n" );
free_suspend_pagedir((unsigned long) pagedir_save);
drivers_resume(RESUME_ALL_PHASES);
spin_unlock_irq(&suspend_pagedir_lock);
drivers_resume(RESUME_ALL_PHASES);
PRINTK( "Fixing swap signatures... " );
mark_swapfiles(((swp_entry_t) {0}), MARK_SWAP_RESUME);
......@@ -804,14 +810,17 @@ void do_magic_suspend_1(void)
{
mb();
barrier();
BUG_ON(in_atomic());
spin_lock_irq(&suspend_pagedir_lock);
}
void do_magic_suspend_2(void)
{
read_swapfiles();
if (!suspend_save_image())
if (!suspend_prepare_image()) { /* suspend_save_image realeses suspend_pagedir_lock */
suspend_save_image();
suspend_power_down(); /* FIXME: if suspend_power_down is commented out, console is lost after few suspends ?! */
}
printk(KERN_EMERG "%sSuspend failed, trying to recover...\n", name_suspend);
MDELAY(1000); /* So user can wait and report us messages if armageddon comes :-) */
......@@ -827,7 +836,7 @@ void do_magic_suspend_2(void)
PRINTK(KERN_WARNING "%sLeaving do_magic_suspend_2...\n", name_suspend);
}
void do_software_suspend(void)
static void do_software_suspend(void)
{
arch_prepare_suspend();
if (prepare_suspend_console())
......@@ -1069,9 +1078,9 @@ static int __read_suspend_image(struct block_device *bdev, union diskpage *cur,
PREPARENEXT; /* We have to read next position before we overwrite it */
if (!memcmp("SUSP1R",cur->swh.magic.magic,6))
if (!memcmp("S1",cur->swh.magic.magic,2))
memcpy(cur->swh.magic.magic,"SWAP-SPACE",10);
else if (!memcmp("SUSP2R",cur->swh.magic.magic,6))
else if (!memcmp("S2",cur->swh.magic.magic,2))
memcpy(cur->swh.magic.magic,"SWAPSPACE2",10);
else {
panic("%sUnable to find suspended-data signature (%.10s - misspelled?\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment