| From d74419495633493c9cd3f2bbeb7f3529d0edded6 Mon Sep 17 00:00:00 2001 |
| From: Heiko Carstens <heiko.carstens@de.ibm.com> |
| Date: Wed, 25 Mar 2015 10:13:33 +0100 |
| Subject: s390/hibernate: fix save and restore of kernel text section |
| |
| From: Heiko Carstens <heiko.carstens@de.ibm.com> |
| |
| commit d74419495633493c9cd3f2bbeb7f3529d0edded6 upstream. |
| |
| Sebastian reported a crash caused by a jump label mismatch after resume. |
| This happens because we do not save the kernel text section during suspend |
| and therefore also do not restore it during resume, but use the kernel image |
| that restores the old system. |
| |
| This means that after a suspend/resume cycle we lost all modifications done |
| to the kernel text section. |
| The reason for this is the pfn_is_nosave() function, which incorrectly |
| returns that read-only pages don't need to be saved. This is incorrect since |
| we mark the kernel text section read-only. |
| We still need to make sure to not save and restore pages contained within |
| NSS and DCSS segment. |
| To fix this add an extra case for the kernel text section and only save |
| those pages if they are not contained within an NSS segment. |
| |
| Fixes the following crash (and the above bugs as well): |
| |
| Jump label code mismatch at netif_receive_skb_internal+0x28/0xd0 |
| Found: c0 04 00 00 00 00 |
| Expected: c0 f4 00 00 00 11 |
| New: c0 04 00 00 00 00 |
| Kernel panic - not syncing: Corrupted kernel text |
| CPU: 0 PID: 9 Comm: migration/0 Not tainted 3.19.0-01975-gb1b096e70f23 #4 |
| Call Trace: |
| [<0000000000113972>] show_stack+0x72/0xf0 |
| [<000000000081f15e>] dump_stack+0x6e/0x90 |
| [<000000000081c4e8>] panic+0x108/0x2b0 |
| [<000000000081be64>] jump_label_bug.isra.2+0x104/0x108 |
| [<0000000000112176>] __jump_label_transform+0x9e/0xd0 |
| [<00000000001121e6>] __sm_arch_jump_label_transform+0x3e/0x50 |
| [<00000000001d1136>] multi_cpu_stop+0x12e/0x170 |
| [<00000000001d1472>] cpu_stopper_thread+0xb2/0x168 |
| [<000000000015d2ac>] smpboot_thread_fn+0x134/0x1b0 |
| [<0000000000158baa>] kthread+0x10a/0x110 |
| [<0000000000824a86>] kernel_thread_starter+0x6/0xc |
| |
| Reported-and-tested-by: Sebastian Ott <sebott@linux.vnet.ibm.com> |
| Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> |
| Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/s390/kernel/suspend.c | 4 ++++ |
| 1 file changed, 4 insertions(+) |
| |
| --- a/arch/s390/kernel/suspend.c |
| +++ b/arch/s390/kernel/suspend.c |
| @@ -142,6 +142,8 @@ int pfn_is_nosave(unsigned long pfn) |
| { |
| unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin)); |
| unsigned long nosave_end_pfn = PFN_DOWN(__pa(&__nosave_end)); |
| + unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1; |
| + unsigned long stext_pfn = PFN_DOWN(__pa(&_stext)); |
| |
| /* Always save lowcore pages (LC protection might be enabled). */ |
| if (pfn <= LC_PAGES) |
| @@ -149,6 +151,8 @@ int pfn_is_nosave(unsigned long pfn) |
| if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn) |
| return 1; |
| /* Skip memory holes and read-only pages (NSS, DCSS, ...). */ |
| + if (pfn >= stext_pfn && pfn <= eshared_pfn) |
| + return ipl_info.type == IPL_TYPE_NSS ? 1 : 0; |
| if (tprot(PFN_PHYS(pfn))) |
| return 1; |
| return 0; |