static int __init relocate_pagedir(void) { /* * We have to avoid recursion (not to overflow kernel stack), * and that's why code looks pretty cryptic */ suspend_pagedir_t *old_pagedir = pm_pagedir_nosave; void **eaten_memory = NULL; void **c = eaten_memory, *m, *f; int err; pr_debug("pmdisk: Relocating pagedir\n"); if(!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) { pr_debug("pmdisk: Relocation not necessary\n"); return 0; } err = -ENOMEM; while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order)) != NULL) { if (!does_collide_order(old_pagedir, (unsigned long)m, pagedir_order)) { pm_pagedir_nosave = memcpy(m, old_pagedir, PAGE_SIZE << pagedir_order); err = 0; break; } eaten_memory = m; printk( "." ); *eaten_memory = c; c = eaten_memory; } c = eaten_memory; while(c) { printk(":"); f = c; c = *c; free_pages((unsigned long)f, pagedir_order); } printk("|\n"); return err; }
static int relocate_pagedir(void) { /* * 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; void **eaten_memory = NULL; void **c = eaten_memory, *m, *f; printk("Relocating pagedir"); if(!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) { printk("not necessary\n"); return 0; } 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; printk( "." ); *eaten_memory = c; c = eaten_memory; } if (!m) return -ENOMEM; pagedir_nosave = new_pagedir = m; copy_pagedir(new_pagedir, old_pagedir); c = eaten_memory; while(c) { printk(":"); f = *c; c = *c; if (f) free_pages((unsigned long)f, pagedir_order); } printk("|\n"); return 0; }
/* * We check here that pagedir & pages it points to won't collide with pages * where we're going to restore from the loaded pages later */ static int __init check_pagedir(void) { int i; for(i=0; i < nr_copy_pages; i++) { unsigned long addr; do { addr = get_zeroed_page(GFP_ATOMIC); if(!addr) return -ENOMEM; } while (does_collide_order(addr, 0)); (pagedir_nosave+i)->address = addr; } return 0; }
static int __init swsusp_pagedir_relocate(void) { /* * We have to avoid recursion (not to overflow kernel stack), * and that's why code looks pretty cryptic */ suspend_pagedir_t *old_pagedir = pagedir_nosave; void **eaten_memory = NULL; void **c = eaten_memory, *m, *f; int ret = 0; struct zone *zone; int i; struct pbe *p; unsigned long zone_pfn; printk("Relocating pagedir "); /* Set page flags */ for_each_zone(zone) { for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn) SetPageNosaveFree(pfn_to_page(zone_pfn + zone->zone_start_pfn)); } /* Clear orig address */ for(i = 0, p = pagedir_nosave; i < nr_copy_pages; i++, p++) { ClearPageNosaveFree(virt_to_page(p->orig_address)); } if (!does_collide_order((unsigned long)old_pagedir, pagedir_order)) { printk("not necessary\n"); return check_pagedir(); } while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order)) != NULL) { if (!does_collide_order((unsigned long)m, pagedir_order)) break; eaten_memory = m; printk( "." ); *eaten_memory = c; c = eaten_memory; } 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) { printk(":"); f = c; c = *c; free_pages((unsigned long)f, pagedir_order); } if (ret) return ret; printk("|\n"); return check_pagedir(); }