Re: [PATCH 2/3] swsusp i386 mark special saveable/unsaveable pages

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 2006-04-19 at 16:33 +1000, Nigel Cunningham wrote:
> Hi.
> 
> On Wednesday 19 April 2006 13:28, Shaohua Li wrote:
> > On Wed, 2006-04-19 at 12:59 +1000, Nigel Cunningham wrote:
> > > Hi.
> > >
> > > On Wednesday 19 April 2006 12:53, Shaohua Li wrote:
> > > > On Wed, 2006-04-19 at 12:08 +1000, Nigel Cunningham wrote:
> > > > > Hi.
> > > > >
> > > > > On Wednesday 19 April 2006 11:51, Shaohua Li wrote:
> > > > > > On Wed, 2006-04-19 at 11:41 +1000, Nigel Cunningham wrote:
> > > > > > > Oh, and while we're on the topic, if only part of a page is NVS,
> > > > > > > what's the right behaviour? My e820 table has:
> > > > > > >
> > > > > > > BIOS-e820: 000000003dff0000 - 000000003dffffc0 (ACPI data)
> > > > > > > BIOS-e820: 000000003dffffc0 - 000000003e000000 (ACPI NVS)
> > > > > >
> > > > > > If only part of a page is NVS, my patch will save the whole page.
> > > > > > Any other idea?
> > > > >
> > > > > A device model driver that handles saving just the part of the page,
> > > > > using preallocated buffers to avoid the potential allocation
> > > > > problems? (The whole page could then safely be Nosave).
> > > >
> > > > The allocation might not be a problem, this just needs one or two extra
> > > > pages. A problem is if just part of the page is NVS, could we touch
> > > > other part (save/restore) the page.
> > >
> > > Yes, so I was thinking of treating it with a pseudo driver that could
> > > save and restore just that portion of the page.
> >
> > Sounds like a good idea. If NVS is already aligned to page size, do you
> > still use the pseudo driver to save/restore the pages? In my system, the
> > NVS memory is 512k.
> > In the other way, we could let the 'swsusp_add_arch_pages' accept
> > address instead of a pfn and let snapshot.c handle the partial page
> > issue.
> 
> I guess the cleanest solution would be to use the same routine in either case. 
> If that was a pseudo driver, it would mean double the memory usage (the pages 
> allocated would also be atomically copied), so perhaps using 
> swsusp_add_arch_pages is the way to go.
Ok, fixed by below patch.
> 
> I wonder too whether Mel Gorman e820 table patches could be leveraged to make 
> finding the NVS data really nice and simple?
Sounds it can't benefit us to me.

patch is on top of the swsusp-add-architecture-special-saveable-pages
patches of 2.6.17-rc1-mm3. Andrew, could you please also queue this
patch in -mm for test? Thanks!

architecture special saveable memory might not be aligned to PAGE_SIZE.
We should just save part of a page in the unaligned case. We changed
swsusp_add_arch_pages to accept an 'address' instead of a 'pfn'.

Signed-off-by: Shaohua Li <[email protected]>
---

 linux-2.6.17-rc1-mm3-root/arch/i386/kernel/setup.c   |   10 ++---
 linux-2.6.17-rc1-mm3-root/arch/x86_64/kernel/setup.c |   10 ++---
 linux-2.6.17-rc1-mm3-root/kernel/power/snapshot.c    |   34 ++++++++++++-------
 3 files changed, 32 insertions(+), 22 deletions(-)

diff -puN kernel/power/snapshot.c~swsusp-add-architecture-special-saveable-pages-fix kernel/power/snapshot.c
--- linux-2.6.17-rc1-mm3/kernel/power/snapshot.c~swsusp-add-architecture-special-saveable-pages-fix	2006-04-18 15:21:45.000000000 +0800
+++ linux-2.6.17-rc1-mm3-root/kernel/power/snapshot.c	2006-04-18 15:27:30.000000000 +0800
@@ -40,8 +40,9 @@ static unsigned int nr_meta_pages;
 static unsigned long *buffer;
 
 struct arch_saveable_page {
-	unsigned long pfn;
-	void *data;
+	unsigned long start;
+	unsigned long end;
+	char *data;
 	struct arch_saveable_page *next;
 };
 static struct arch_saveable_page *arch_pages;
@@ -50,13 +51,16 @@ int swsusp_add_arch_pages(unsigned long 
 {
 	struct arch_saveable_page *tmp;
 
-	while (start <= end) {
+	while (start < end) {
 		tmp = kzalloc(sizeof(struct arch_saveable_page), GFP_KERNEL);
 		if (!tmp)
 			return -ENOMEM;
-		tmp->pfn = start;
+		tmp->start = start;
+		tmp->end = ((start >> PAGE_SHIFT) + 1) << PAGE_SHIFT;
+		if (tmp->end > end)
+			tmp->end = end;
 		tmp->next = arch_pages;
-		start++;
+		start = tmp->end;
 		arch_pages = tmp;
 	}
 	return 0;
@@ -75,17 +79,20 @@ static unsigned int count_arch_pages(voi
 
 static int save_arch_mem(void)
 {
-	void *kaddr;
+	char *kaddr;
 	struct arch_saveable_page *tmp = arch_pages;
+	int offset;
 
 	pr_debug("swsusp: Saving arch specific memory");
 	while (tmp) {
-		tmp->data = (void *)__get_free_page(GFP_ATOMIC);
+		tmp->data = (char *)__get_free_page(GFP_ATOMIC);
 		if (!tmp->data)
 			return -ENOMEM;
+		offset = tmp->start - (tmp->start & PAGE_MASK);
 		/* arch pages might haven't a 'struct page' */
-		kaddr = kmap_atomic_pfn(tmp->pfn, KM_USER0);
-		memcpy(tmp->data, kaddr, PAGE_SIZE);
+		kaddr = kmap_atomic_pfn(tmp->start >> PAGE_SHIFT, KM_USER0);
+		memcpy(tmp->data + offset, kaddr + offset,
+			tmp->end - tmp->start);
 		kunmap_atomic(kaddr, KM_USER0);
 
 		tmp = tmp->next;
@@ -95,14 +102,17 @@ static int save_arch_mem(void)
 
 static int restore_arch_mem(void)
 {
-	void *kaddr;
+	char *kaddr;
 	struct arch_saveable_page *tmp = arch_pages;
+	int offset;
 
 	while (tmp) {
 		if (!tmp->data)
 			continue;
-		kaddr = kmap_atomic_pfn(tmp->pfn, KM_USER0);
-		memcpy(kaddr, tmp->data, PAGE_SIZE);
+		offset = tmp->start - (tmp->start & PAGE_MASK);
+		kaddr = kmap_atomic_pfn(tmp->start >> PAGE_SHIFT, KM_USER0);
+		memcpy(kaddr + offset, tmp->data + offset,
+			tmp->end - tmp->start);
 		kunmap_atomic(kaddr, KM_USER0);
 		free_page((long)tmp->data);
 		tmp->data = NULL;
diff -puN arch/i386/kernel/setup.c~swsusp-add-architecture-special-saveable-pages-fix arch/i386/kernel/setup.c
--- linux-2.6.17-rc1-mm3/arch/i386/kernel/setup.c~swsusp-add-architecture-special-saveable-pages-fix	2006-04-18 15:28:00.000000000 +0800
+++ linux-2.6.17-rc1-mm3-root/arch/i386/kernel/setup.c	2006-04-18 15:29:26.000000000 +0800
@@ -1500,8 +1500,8 @@ static void __init e820_save_acpi_pages(
 		struct e820entry *ei = &e820.map[i];
 		unsigned long start, end;
 
-		start = PFN_DOWN(ei->addr);
-		end = PFN_UP(ei->addr + ei->size);
+		start = ei->addr;
+		end = ei->addr + ei->size;
 		if (start >= end)
 			continue;
 		if (ei->type != E820_ACPI && ei->type != E820_NVS)
@@ -1510,15 +1510,15 @@ static void __init e820_save_acpi_pages(
 		 * If the region is below max_low_pfn, it will be
 		 * saved/restored by swsusp follow 'RAM' type.
 		 */
-		if (start < max_low_pfn)
-			start = max_low_pfn;
+		if (start < (max_low_pfn << PAGE_SHIFT))
+			start = max_low_pfn << PAGE_SHIFT;
 		/*
 		 * Highmem pages (ACPI NVS/Data) are reserved, but swsusp
 		 * highmem save/restore will not save/restore them. We marked
 		 * them as arch saveable pages here
 		 */
 		if (end > start)
-			swsusp_add_arch_pages(start, end - 1);
+			swsusp_add_arch_pages(start, end);
 	}
 }
 
diff -puN arch/x86_64/kernel/setup.c~swsusp-add-architecture-special-saveable-pages-fix arch/x86_64/kernel/setup.c
--- linux-2.6.17-rc1-mm3/arch/x86_64/kernel/setup.c~swsusp-add-architecture-special-saveable-pages-fix	2006-04-18 15:28:07.000000000 +0800
+++ linux-2.6.17-rc1-mm3-root/arch/x86_64/kernel/setup.c	2006-04-18 15:31:31.000000000 +0800
@@ -564,8 +564,8 @@ static void __init e820_save_acpi_pages(
 		struct e820entry *ei = &e820.map[i];
 		unsigned long start, end;
 
-		start = round_down(ei->addr, PAGE_SIZE) >> PAGE_SHIFT;
-		end = round_up(ei->addr + ei->size, PAGE_SIZE) >> PAGE_SHIFT;
+		start = ei->addr, PAGE_SIZE;
+		end = ei->addr + ei->size;
 		if (start >= end)
 			continue;
 		if (ei->type != E820_ACPI && ei->type != E820_NVS)
@@ -574,10 +574,10 @@ static void __init e820_save_acpi_pages(
 		 * If the region is below end_pfn, it will be
 		 * saved/restored by swsusp follow 'RAM' type.
 		 */
-		if (start < end_pfn)
-			start = end_pfn;
+		if (start < (end_pfn << PAGE_SHIFT))
+			start = end_pfn << PAGE_SHIFT;
 		if (end > start)
-			swsusp_add_arch_pages(start, end - 1);
+			swsusp_add_arch_pages(start, end);
 	}
 }
 
_


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux