Re: [PATCH -mm 2/2] Hibernation: Arbitrary boot kernel support on x86_64 (updated)

2007-08-27 Thread Pavel Machek
On Sat 2007-08-25 22:42:05, Rafael J. Wysocki wrote:
> On Saturday, 25 August 2007 20:27, Rafael J. Wysocki wrote:
> > On Friday, 24 August 2007 22:46, Pavel Machek wrote:
> > > Hi!
> > > 
> > > > From: Rafael J. Wysocki <[EMAIL PROTECTED]>
> > > > 
> > > > Make it possible to restore a hibernation image on x86_64 with the help 
> > > > of a
> > > > kernel different from the one in the image.
> > > > 
> > > > The idea is to split the core restoration code into two separate parts 
> > > > and to
> > > > place each of them in a different page.  The first part belongs to the 
> > > > boot
> > > 
> > > What happens in case where both parts want to be
> > > at the same place? (Like kernel being restored is 4KB smaller, so that
> > > routines now collide?)
> > 
> > Bad things, but I can't see how to avoid that reliably.
> 
> Below is an analogous patch without this problem.  The slightly ugly thing
> about it is that all pages in the temporary mapping have the NX bit cleard
> now, so that we can run some code out of one of them.  Still, IMO, that isn't
> really important, because the temporary page tables are dropped as soon as
> we jump to restore_registers.
> 
> Greetings,
> Rafael
> 
> ---
> From: Rafael J. Wysocki <[EMAIL PROTECTED]>
> 
> Make it possible to restore a hibernation image on x86_64 with the help of a
> kernel different from the one in the image.
> 
> The idea is to split the core restoration code into two separate parts and to
> place each of them in a different page.  The first part belongs to the boot
> kernel and is executed as the last step of the image kernel's memory 
> restoration
> procedure.  Before being executed, it is relocated to a safe page that won't 
> be
> overwritten while copying the image kernel pages.
> 
> The final operation performed by it is a jump to the second part of the core
> restoration code that belongs to the image kernel and has just been restored.
> This code makes the CPU switch to the image kernel's page tables and
> restores the state of general purpose registers (including the stack pointer)
> from before the hibernation.
> 
> The main issue with this idea is that in order to jump to the second part of 
> the
> core restoration code the boot kernel needs to know its address.  However, 
> this
> address may be passed to it in the image header.  Namely, the part of the 
> image
> header previously used for checking if the version of the image kernel is
> correct can be replaced with some architecture specific data that will allow
> the boot kernel to jump to the right address within the image kernel.  These
> data should also be used for checking if the image kernel is compatible with
> the boot kernel (as far as the memory restroration procedure is concerned).
> It can be done, for example, with the help of a "magic" value that has to be
> equal in both kernels, so that they can be regarded as compatible.
> 
> Signed-off-by: Rafael J. Wysocki <[EMAIL PROTECTED]>
ACK.
Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-
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/


Re: [PATCH -mm 2/2] Hibernation: Arbitrary boot kernel support on x86_64 (updated)

2007-08-27 Thread Pavel Machek
On Sat 2007-08-25 22:42:05, Rafael J. Wysocki wrote:
 On Saturday, 25 August 2007 20:27, Rafael J. Wysocki wrote:
  On Friday, 24 August 2007 22:46, Pavel Machek wrote:
   Hi!
   
From: Rafael J. Wysocki [EMAIL PROTECTED]

Make it possible to restore a hibernation image on x86_64 with the help 
of a
kernel different from the one in the image.

The idea is to split the core restoration code into two separate parts 
and to
place each of them in a different page.  The first part belongs to the 
boot
   
   What happens in case where both parts want to be
   at the same place? (Like kernel being restored is 4KB smaller, so that
   routines now collide?)
  
  Bad things, but I can't see how to avoid that reliably.
 
 Below is an analogous patch without this problem.  The slightly ugly thing
 about it is that all pages in the temporary mapping have the NX bit cleard
 now, so that we can run some code out of one of them.  Still, IMO, that isn't
 really important, because the temporary page tables are dropped as soon as
 we jump to restore_registers.
 
 Greetings,
 Rafael
 
 ---
 From: Rafael J. Wysocki [EMAIL PROTECTED]
 
 Make it possible to restore a hibernation image on x86_64 with the help of a
 kernel different from the one in the image.
 
 The idea is to split the core restoration code into two separate parts and to
 place each of them in a different page.  The first part belongs to the boot
 kernel and is executed as the last step of the image kernel's memory 
 restoration
 procedure.  Before being executed, it is relocated to a safe page that won't 
 be
 overwritten while copying the image kernel pages.
 
 The final operation performed by it is a jump to the second part of the core
 restoration code that belongs to the image kernel and has just been restored.
 This code makes the CPU switch to the image kernel's page tables and
 restores the state of general purpose registers (including the stack pointer)
 from before the hibernation.
 
 The main issue with this idea is that in order to jump to the second part of 
 the
 core restoration code the boot kernel needs to know its address.  However, 
 this
 address may be passed to it in the image header.  Namely, the part of the 
 image
 header previously used for checking if the version of the image kernel is
 correct can be replaced with some architecture specific data that will allow
 the boot kernel to jump to the right address within the image kernel.  These
 data should also be used for checking if the image kernel is compatible with
 the boot kernel (as far as the memory restroration procedure is concerned).
 It can be done, for example, with the help of a magic value that has to be
 equal in both kernels, so that they can be regarded as compatible.
 
 Signed-off-by: Rafael J. Wysocki [EMAIL PROTECTED]
ACK.
Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) 
http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-
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/


[PATCH -mm 2/2] Hibernation: Arbitrary boot kernel support on x86_64 (updated)

2007-08-25 Thread Rafael J. Wysocki
On Saturday, 25 August 2007 20:27, Rafael J. Wysocki wrote:
> On Friday, 24 August 2007 22:46, Pavel Machek wrote:
> > Hi!
> > 
> > > From: Rafael J. Wysocki <[EMAIL PROTECTED]>
> > > 
> > > Make it possible to restore a hibernation image on x86_64 with the help 
> > > of a
> > > kernel different from the one in the image.
> > > 
> > > The idea is to split the core restoration code into two separate parts 
> > > and to
> > > place each of them in a different page.  The first part belongs to the 
> > > boot
> > 
> > What happens in case where both parts want to be
> > at the same place? (Like kernel being restored is 4KB smaller, so that
> > routines now collide?)
> 
> Bad things, but I can't see how to avoid that reliably.

Below is an analogous patch without this problem.  The slightly ugly thing
about it is that all pages in the temporary mapping have the NX bit cleard
now, so that we can run some code out of one of them.  Still, IMO, that isn't
really important, because the temporary page tables are dropped as soon as
we jump to restore_registers.

Greetings,
Rafael

---
From: Rafael J. Wysocki <[EMAIL PROTECTED]>

Make it possible to restore a hibernation image on x86_64 with the help of a
kernel different from the one in the image.

The idea is to split the core restoration code into two separate parts and to
place each of them in a different page.  The first part belongs to the boot
kernel and is executed as the last step of the image kernel's memory restoration
procedure.  Before being executed, it is relocated to a safe page that won't be
overwritten while copying the image kernel pages.

The final operation performed by it is a jump to the second part of the core
restoration code that belongs to the image kernel and has just been restored.
This code makes the CPU switch to the image kernel's page tables and
restores the state of general purpose registers (including the stack pointer)
from before the hibernation.

The main issue with this idea is that in order to jump to the second part of the
core restoration code the boot kernel needs to know its address.  However, this
address may be passed to it in the image header.  Namely, the part of the image
header previously used for checking if the version of the image kernel is
correct can be replaced with some architecture specific data that will allow
the boot kernel to jump to the right address within the image kernel.  These
data should also be used for checking if the image kernel is compatible with
the boot kernel (as far as the memory restroration procedure is concerned).
It can be done, for example, with the help of a "magic" value that has to be
equal in both kernels, so that they can be regarded as compatible.

Signed-off-by: Rafael J. Wysocki <[EMAIL PROTECTED]>
---
 arch/x86_64/Kconfig  |5 +++
 arch/x86_64/kernel/suspend.c |   54 ++-
 arch/x86_64/kernel/suspend_asm.S |   41 -
 include/asm-x86_64/suspend.h |3 ++
 4 files changed, 95 insertions(+), 8 deletions(-)

Index: linux-2.6.23-rc3/arch/x86_64/kernel/suspend_asm.S
===
--- linux-2.6.23-rc3.orig/arch/x86_64/kernel/suspend_asm.S  2007-08-25 
22:09:53.0 +0200
+++ linux-2.6.23-rc3/arch/x86_64/kernel/suspend_asm.S   2007-08-25 
22:10:25.0 +0200
@@ -2,8 +2,8 @@
  *
  * Distribute under GPLv2.
  *
- * swsusp_arch_resume may not use any stack, nor any variable that is
- * not "NoSave" during copying pages:
+ * swsusp_arch_resume must not use any stack or any nonlocal variables while
+ * copying pages:
  *
  * Its rewriting one kernel image with another. What is stack in "old"
  * image could very well be data page in "new" image, and overwriting
@@ -36,6 +36,10 @@ ENTRY(swsusp_arch_suspend)
pushfq
popqpt_regs_eflags(%rax)
 
+   /* save the address of restore_registers */
+   movq$restore_registers, %rax
+   movq%rax, restore_jump_address(%rip)
+
call swsusp_save
ret
 
@@ -54,7 +58,16 @@ ENTRY(restore_image)
movq%rcx, %cr3;
movq%rax, %cr4;  # turn PGE back on
 
+   /* prepare to jump to the image kernel */
+   movqrestore_jump_address(%rip), %rax
+
+   /* prepare to copy image data to their original locations */
movqrestore_pblist(%rip), %rdx
+   movqrelocated_restore_code(%rip), %rcx
+   jmpq*%rcx
+
+   /* code below has been relocated to a safe page */
+ENTRY(core_restore_code)
 loop:
testq   %rdx, %rdx
jz  done
@@ -62,7 +75,7 @@ loop:
/* get addresses from the pbe and copy the page */
movqpbe_address(%rdx), %rsi
movqpbe_orig_address(%rdx), %rdi
-   movq$512, %rcx
+   movq$(PAGE_SIZE >> 3), %rcx
rep
movsq
 
@@ -70,6 +83,20 @@ loop:
movqpbe_next(%rdx), %rdx
jmp loop
 done:
+   /* jump to 

[PATCH -mm 2/2] Hibernation: Arbitrary boot kernel support on x86_64 (updated)

2007-08-25 Thread Rafael J. Wysocki
On Saturday, 25 August 2007 20:27, Rafael J. Wysocki wrote:
 On Friday, 24 August 2007 22:46, Pavel Machek wrote:
  Hi!
  
   From: Rafael J. Wysocki [EMAIL PROTECTED]
   
   Make it possible to restore a hibernation image on x86_64 with the help 
   of a
   kernel different from the one in the image.
   
   The idea is to split the core restoration code into two separate parts 
   and to
   place each of them in a different page.  The first part belongs to the 
   boot
  
  What happens in case where both parts want to be
  at the same place? (Like kernel being restored is 4KB smaller, so that
  routines now collide?)
 
 Bad things, but I can't see how to avoid that reliably.

Below is an analogous patch without this problem.  The slightly ugly thing
about it is that all pages in the temporary mapping have the NX bit cleard
now, so that we can run some code out of one of them.  Still, IMO, that isn't
really important, because the temporary page tables are dropped as soon as
we jump to restore_registers.

Greetings,
Rafael

---
From: Rafael J. Wysocki [EMAIL PROTECTED]

Make it possible to restore a hibernation image on x86_64 with the help of a
kernel different from the one in the image.

The idea is to split the core restoration code into two separate parts and to
place each of them in a different page.  The first part belongs to the boot
kernel and is executed as the last step of the image kernel's memory restoration
procedure.  Before being executed, it is relocated to a safe page that won't be
overwritten while copying the image kernel pages.

The final operation performed by it is a jump to the second part of the core
restoration code that belongs to the image kernel and has just been restored.
This code makes the CPU switch to the image kernel's page tables and
restores the state of general purpose registers (including the stack pointer)
from before the hibernation.

The main issue with this idea is that in order to jump to the second part of the
core restoration code the boot kernel needs to know its address.  However, this
address may be passed to it in the image header.  Namely, the part of the image
header previously used for checking if the version of the image kernel is
correct can be replaced with some architecture specific data that will allow
the boot kernel to jump to the right address within the image kernel.  These
data should also be used for checking if the image kernel is compatible with
the boot kernel (as far as the memory restroration procedure is concerned).
It can be done, for example, with the help of a magic value that has to be
equal in both kernels, so that they can be regarded as compatible.

Signed-off-by: Rafael J. Wysocki [EMAIL PROTECTED]
---
 arch/x86_64/Kconfig  |5 +++
 arch/x86_64/kernel/suspend.c |   54 ++-
 arch/x86_64/kernel/suspend_asm.S |   41 -
 include/asm-x86_64/suspend.h |3 ++
 4 files changed, 95 insertions(+), 8 deletions(-)

Index: linux-2.6.23-rc3/arch/x86_64/kernel/suspend_asm.S
===
--- linux-2.6.23-rc3.orig/arch/x86_64/kernel/suspend_asm.S  2007-08-25 
22:09:53.0 +0200
+++ linux-2.6.23-rc3/arch/x86_64/kernel/suspend_asm.S   2007-08-25 
22:10:25.0 +0200
@@ -2,8 +2,8 @@
  *
  * Distribute under GPLv2.
  *
- * swsusp_arch_resume may not use any stack, nor any variable that is
- * not NoSave during copying pages:
+ * swsusp_arch_resume must not use any stack or any nonlocal variables while
+ * copying pages:
  *
  * Its rewriting one kernel image with another. What is stack in old
  * image could very well be data page in new image, and overwriting
@@ -36,6 +36,10 @@ ENTRY(swsusp_arch_suspend)
pushfq
popqpt_regs_eflags(%rax)
 
+   /* save the address of restore_registers */
+   movq$restore_registers, %rax
+   movq%rax, restore_jump_address(%rip)
+
call swsusp_save
ret
 
@@ -54,7 +58,16 @@ ENTRY(restore_image)
movq%rcx, %cr3;
movq%rax, %cr4;  # turn PGE back on
 
+   /* prepare to jump to the image kernel */
+   movqrestore_jump_address(%rip), %rax
+
+   /* prepare to copy image data to their original locations */
movqrestore_pblist(%rip), %rdx
+   movqrelocated_restore_code(%rip), %rcx
+   jmpq*%rcx
+
+   /* code below has been relocated to a safe page */
+ENTRY(core_restore_code)
 loop:
testq   %rdx, %rdx
jz  done
@@ -62,7 +75,7 @@ loop:
/* get addresses from the pbe and copy the page */
movqpbe_address(%rdx), %rsi
movqpbe_orig_address(%rdx), %rdi
-   movq$512, %rcx
+   movq$(PAGE_SIZE  3), %rcx
rep
movsq
 
@@ -70,6 +83,20 @@ loop:
movqpbe_next(%rdx), %rdx
jmp loop
 done:
+   /* jump to the restore_registers address from the image header */
+