if (!pbe)
continue;
pbe->orig_address = (long) page_address(page);
+ /* Copy page is dangerous: it likes to mess with
+ preempt count on specific cpus. Wrong preempt count is then copied,
+ oops. */
copy_page((void *)pbe->address, (void *)pbe->orig_address);
pbe++;
}
/* More restore stuff */
-/* FIXME: Why not memcpy(to, from, 1<<pagedir_order*PAGE_SIZE)? */
-static void copy_pagedir(suspend_pagedir_t *to, suspend_pagedir_t *from)
-{
- int i;
- char *topointer=(char *)to, *frompointer=(char *)from;
-
- for(i=0; i < 1 << pagedir_order; i++) {
- copy_page(topointer, frompointer);
- topointer += PAGE_SIZE;
- frompointer += PAGE_SIZE;
- }
-}
-
#define does_collide(addr) does_collide_order(pagedir_nosave, addr, 0)
/*
* We have to avoid recursion (not to overflow kernel stack),
* and that's why code looks pretty cryptic
*/
- suspend_pagedir_t *new_pagedir, *old_pagedir = pagedir_nosave;
+ suspend_pagedir_t *old_pagedir = pagedir_nosave;
void **eaten_memory = NULL;
void **c = eaten_memory, *m, *f;
+ int ret = 0;
- printk("Relocating pagedir");
+ printk("Relocating pagedir ");
if(!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) {
printk("not necessary\n");
}
while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order))) {
- memset(m, 0, PAGE_SIZE);
if (!does_collide_order(old_pagedir, (unsigned long)m, pagedir_order))
break;
eaten_memory = m;
c = eaten_memory;
}
- if (!m)
- return -ENOMEM;
-
- pagedir_nosave = new_pagedir = m;
- copy_pagedir(new_pagedir, old_pagedir);
+ if (!m) {
+ printk("out of memory\n");
+ ret = -ENOMEM;
+ } else {
+ pagedir_nosave =
+ memcpy(m, old_pagedir, PAGE_SIZE << pagedir_order);
+ }
c = eaten_memory;
- while(c) {
+ while (c) {
printk(":");
- f = *c;
+ f = c;
c = *c;
- if (f)
- free_pages((unsigned long)f, pagedir_order);
+ free_pages((unsigned long)f, pagedir_order);
}
printk("|\n");
- return 0;
+ return ret;
}
/*