From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 10:12:18
Changelog:
v10:
- Addressed a lot of comments form James Morse and from Marc Zyngier
- Added review-by's
- Synchronized with mainline
v9: - 9 patches from previous series landed in upstream, so now series
is smaller
- Added two patches from James Morse to address idmap issues for machines
with high physical addresses.
- Addressed comments from Selin Dag about compiling issues. He also tested
my series and got similar performance results: ~60 ms instead of ~580 ms
with an initramfs size of ~120MB.
v8:
- Synced with mainline to keep series up-to-date
v7:
-- Addressed comments from James Morse
- arm64: hibernate: pass the allocated pgdp to ttbr0
Removed "Fixes" tag, and added Added Reviewed-by: James Morse
- arm64: hibernate: check pgd table allocation
Sent out as a standalone patch so it can be sent to stable
Series applies on mainline + this patch
- arm64: hibernate: add trans_pgd public functions
Remove second allocation of tmp_pg_dir in swsusp_arch_resume
Added Reviewed-by: James Morse [off-list ref]
- arm64: kexec: move relocation function setup and clean up
Fixed typo in commit log
Changed kern_reloc to phys_addr_t types.
Added explanation why kern_reloc is needed.
Split into four patches:
arm64: kexec: make dtb_mem always enabled
arm64: kexec: remove unnecessary debug prints
arm64: kexec: call kexec_image_info only once
arm64: kexec: move relocation function setup
- arm64: kexec: add expandable argument to relocation function
Changed types of new arguments from unsigned long to phys_addr_t.
Changed offset prefix to KEXEC_*
Split into four patches:
arm64: kexec: cpu_soft_restart change argument types
arm64: kexec: arm64_relocate_new_kernel clean-ups
arm64: kexec: arm64_relocate_new_kernel don't use x0 as temp
arm64: kexec: add expandable argument to relocation function
- arm64: kexec: configure trans_pgd page table for kexec
Added invalid entries into EL2 vector table
Removed KEXEC_EL2_VECTOR_TABLE_SIZE and KEXEC_EL2_VECTOR_TABLE_OFFSET
Copy relocation functions and table into separate pages
Changed types in kern_reloc_arg.
Split into three patches:
arm64: kexec: offset for relocation function
arm64: kexec: kexec EL2 vectors
arm64: kexec: configure trans_pgd page table for kexec
- arm64: kexec: enable MMU during kexec relocation
Split into two patches:
arm64: kexec: enable MMU during kexec relocation
arm64: kexec: remove head from relocation argument
v6:
- Sync with mainline tip
- Added Acked's from Dave Young
v5:
- Addressed comments from Matthias Brugger: added review-by's, improved
comments, and made cleanups to swsusp_arch_resume() in addition to
create_safe_exec_page().
- Synced with mainline tip.
v4:
- Addressed comments from James Morse.
- Split "check pgd table allocation" into two patches, and moved to
the beginning of series for simpler backport of the fixes.
Added "Fixes:" tags to commit logs.
- Changed "arm64, hibernate:" to "arm64: hibernate:"
- Added Reviewed-by's
- Moved "add PUD_SECT_RDONLY" earlier in series to be with other
clean-ups
- Added "Derived from:" to arch/arm64/mm/trans_pgd.c
- Removed "flags" from trans_info
- Changed .trans_alloc_page assumption to return zeroed page.
- Simplify changes to trans_pgd_map_page(), by keeping the old
code.
- Simplify changes to trans_pgd_create_copy, by keeping the old
code.
- Removed: "add trans_pgd_create_empty"
- replace init_mm with NULL, and keep using non "__" version of
populate functions.
v3:
- Split changes to create_safe_exec_page() into several patches for
easier review as request by Mark Rutland. This is why this series
has 3 more patches.
- Renamed trans_table to tans_pgd as agreed with Mark. The header
comment in trans_pgd.c explains that trans stands for
transitional page tables. Meaning they are used in transition
between two kernels.
v2:
- Fixed hibernate bug reported by James Morse
- Addressed comments from James Morse:
* More incremental changes to trans_table
* Removed TRANS_FORCEMAP
* Added kexec reboot data for image with 380M in size.
Enable MMU during kexec relocation in order to improve reboot performance.
If kexec functionality is used for a fast system update, with a minimal
downtime, the relocation of kernel + initramfs takes a significant portion
of reboot.
The reason for slow relocation is because it is done without MMU, and thus
not benefiting from D-Cache.
Performance data
----------------
For this experiment, the size of kernel plus initramfs is small, only 25M.
If initramfs was larger, than the improvements would be greater, as time
spent in relocation is proportional to the size of relocation.
Previously:
kernel shutdown 0.022131328s
relocation 0.440510736s
kernel startup 0.294706768s
Relocation was taking: 58.2% of reboot time
Now:
kernel shutdown 0.032066576s
relocation 0.022158152s
kernel startup 0.296055880s
Now: Relocation takes 6.3% of reboot time
Total reboot is x2.16 times faster.
With bigger userland (fitImage 380M), the reboot time is improved by 3.57s,
and is reduced from 3.9s down to 0.33s
Previous approaches and discussions
-----------------------------------
v9: https://lore.kernel.org/lkml/20200326032420.27220-1-pasha.tatashin@soleen.com
v8: https://lore.kernel.org/lkml/20191204155938.2279686-1-pasha.tatashin@soleen.com
v7: https://lore.kernel.org/lkml/20191016200034.1342308-1-pasha.tatashin@soleen.com
v6: https://lore.kernel.org/lkml/20191004185234.31471-1-pasha.tatashin@soleen.com
v5: https://lore.kernel.org/lkml/20190923203427.294286-1-pasha.tatashin@soleen.com
v4: https://lore.kernel.org/lkml/20190909181221.309510-1-pasha.tatashin@soleen.com
v3: https://lore.kernel.org/lkml/20190821183204.23576-1-pasha.tatashin@soleen.com
v2: https://lore.kernel.org/lkml/20190817024629.26611-1-pasha.tatashin@soleen.com
v1: https://lore.kernel.org/lkml/20190801152439.11363-1-pasha.tatashin@soleen.com
Older approaches:
https://lore.kernel.org/lkml/20190709182014.16052-1-pasha.tatashin@soleen.com
reserve space for kexec to avoid relocation, involves changes to generic code
to optimize a problem that exists on arm64 only:
https://lore.kernel.org/lkml/20190716165641.6990-1-pasha.tatashin@soleen.com
The first attempt to enable MMU, some bugs that prevented performance
improvement. The page tables unnecessary configured idmap for the whole
physical space.
https://lore.kernel.org/lkml/20190731153857.4045-1-pasha.tatashin@soleen.com
No linear copy, bug with EL2 reboots.
James Morse (2):
arm64: mm: Always update TCR_EL1 from __cpu_set_tcr_t0sz()
arm64: trans_pgd: hibernate: idmap the single page that holds the copy
page routines
Pavel Tatashin (16):
arm64: kexec: make dtb_mem always enabled
arm64: hibernate: variable pudp is used instead of pd4dp
arm64: hibernate: move page handling function to new trans_pgd.c
arm64: trans_pgd: make trans_pgd_map_page generic
arm64: trans_pgd: pass allocator trans_pgd_create_copy
arm64: trans_pgd: pass NULL instead of init_mm to *_populate functions
arm64: kexec: move relocation function setup
arm64: kexec: call kexec_image_info only once
arm64: kexec: arm64_relocate_new_kernel clean-ups and optimizations
arm64: kexec: arm64_relocate_new_kernel don't use x0 as temp
arm64: kexec: add expandable argument to relocation function
arm64: kexec: use ld script for relocation function
arm64: kexec: kexec may require EL2 vectors
arm64: kexec: configure trans_pgd page table for kexec
arm64: kexec: enable MMU during kexec relocation
arm64: kexec: remove head from relocation argument
arch/arm64/Kconfig | 4 +
arch/arm64/include/asm/kexec.h | 42 +++-
arch/arm64/include/asm/mmu_context.h | 7 +-
arch/arm64/include/asm/sections.h | 1 +
arch/arm64/include/asm/trans_pgd.h | 39 ++++
arch/arm64/kernel/asm-offsets.c | 15 ++
arch/arm64/kernel/cpu-reset.S | 11 +-
arch/arm64/kernel/cpu-reset.h | 8 +-
arch/arm64/kernel/hibernate.c | 271 +++-------------------
arch/arm64/kernel/machine_kexec.c | 182 +++++++++++----
arch/arm64/kernel/relocate_kernel.S | 218 ++++++++++--------
arch/arm64/kernel/vmlinux.lds.S | 19 ++
arch/arm64/mm/Makefile | 1 +
arch/arm64/mm/trans_pgd.c | 324 +++++++++++++++++++++++++++
14 files changed, 749 insertions(+), 393 deletions(-)
create mode 100644 arch/arm64/include/asm/trans_pgd.h
create mode 100644 arch/arm64/mm/trans_pgd.c
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-25 19:40:21
From: James Morse <james.morse@arm.com>
Because only the idmap sets a non-standard T0SZ, __cpu_set_tcr_t0sz()
can check for platforms that need to do this using
__cpu_uses_extended_idmap() before doing its work.
The idmap is only built with enough levels, (and T0SZ bits) to map
its single page.
To allow hibernate, and then kexec to idmap their single page copy
routines, __cpu_set_tcr_t0sz() needs to consider additional users,
who may need a different number of levels/T0SZ-bits to the idmap.
(i.e. VA_BITS may be enough for the idmap, but not hibernate/kexec)
Always read TCR_EL1, and check whether any work needs doing for
this request. __cpu_uses_extended_idmap() remains as it is used
by KVM, whose idmap is also part of the kernel image.
This mostly affects the cpuidle path, where we now get an extra
system register read .
CC: Lorenzo Pieralisi <redacted>
CC: Sudeep Holla <redacted>
Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/include/asm/mmu_context.h | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-25 19:42:08
If we have a EL2 mode without VHE, the EL2 vectors are needed in order
to switch to EL2 and jump to new world with hypervisor privileges.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/include/asm/kexec.h | 5 +++++
arch/arm64/kernel/asm-offsets.c | 1 +
arch/arm64/kernel/machine_kexec.c | 9 +++++++-
arch/arm64/kernel/relocate_kernel.S | 35 +++++++++++++++++++++++++++++
4 files changed, 49 insertions(+), 1 deletion(-)
@@ -75,19 +75,26 @@ int machine_kexec_post_load(struct kimage *kimage){void*reloc_code=page_to_virt(kimage->control_code_page);structkern_reloc_arg*kern_reloc_arg=kexec_page_alloc(kimage);-longfunc_offset,reloc_size;+longfunc_offset,vector_offset,reloc_size;if(!kern_reloc_arg)return-ENOMEM;func_offset=arm64_relocate_new_kernel-__relocate_new_kernel_start;reloc_size=__relocate_new_kernel_end-__relocate_new_kernel_start;+vector_offset=arm64_kexec_el2_vectors-__relocate_new_kernel_start;+memcpy(reloc_code,__relocate_new_kernel_start,reloc_size);kimage->arch.kern_reloc=__pa(reloc_code)+func_offset;kimage->arch.kern_reloc_arg=__pa(kern_reloc_arg);kern_reloc_arg->head=kimage->head;kern_reloc_arg->entry_addr=kimage->start;kern_reloc_arg->kern_arg0=kimage->arch.dtb_mem;++/* Setup vector table only when EL2 is available, but no VHE */+if(is_hyp_mode_available()&&!is_kernel_in_hyp_mode())+kern_reloc_arg->el2_vector=__pa(reloc_code)+vector_offset;+kexec_image_info(kimage);/* Flush the reloc_code in preparation for its execution. */
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-25 19:43:08
Now, that we have transitional page tables configured, temporarily enable
MMU to allow faster relocation of segments to final destination.
The performance data: for a moderate size kernel + initramfs: 25M the
relocation was taking 0.382s, with enabled MMU it now takes
0.019s only or x20 improvement.
The time is proportional to the size of relocation, therefore if initramfs
is larger, 100M it could take over a second.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/kernel/relocate_kernel.S | 131 ++++++++++++++++++----------
1 file changed, 87 insertions(+), 44 deletions(-)
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-25 19:44:31
Make trans_pgd_create_copy and its subroutines to use allocator that is
passed as an argument
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: James Morse <james.morse@arm.com>
---
arch/arm64/include/asm/trans_pgd.h | 4 +--
arch/arm64/kernel/hibernate.c | 7 ++++-
arch/arm64/mm/trans_pgd.c | 49 ++++++++++++++++++------------
3 files changed, 38 insertions(+), 22 deletions(-)
@@ -78,8 +78,8 @@ static int copy_pte(pmd_t *dst_pmdp, pmd_t *src_pmdp, unsigned long start,return0;}-staticintcopy_pmd(pud_t*dst_pudp,pud_t*src_pudp,unsignedlongstart,-unsignedlongend)+staticintcopy_pmd(structtrans_pgd_info*info,pud_t*dst_pudp,+pud_t*src_pudp,unsignedlongstart,unsignedlongend){pmd_t*src_pmdp;pmd_t*dst_pmdp;
@@ -87,7 +87,7 @@ static int copy_pmd(pud_t *dst_pudp, pud_t *src_pudp, unsigned long start,unsignedlongaddr=start;if(pud_none(READ_ONCE(*dst_pudp))){-dst_pmdp=(pmd_t*)get_safe_page(GFP_ATOMIC);+dst_pmdp=trans_alloc(info);if(!dst_pmdp)return-ENOMEM;pud_populate(&init_mm,dst_pudp,dst_pmdp);
@@ -102,7 +102,7 @@ static int copy_pmd(pud_t *dst_pudp, pud_t *src_pudp, unsigned long start,if(pmd_none(pmd))continue;if(pmd_table(pmd)){-if(copy_pte(dst_pmdp,src_pmdp,addr,next))+if(copy_pte(info,dst_pmdp,src_pmdp,addr,next))return-ENOMEM;}else{set_pmd(dst_pmdp,
@@ -113,7 +113,8 @@ static int copy_pmd(pud_t *dst_pudp, pud_t *src_pudp, unsigned long start,return0;}-staticintcopy_pud(p4d_t*dst_p4dp,p4d_t*src_p4dp,unsignedlongstart,+staticintcopy_pud(structtrans_pgd_info*info,p4d_t*dst_p4dp,+p4d_t*src_p4dp,unsignedlongstart,unsignedlongend){pud_t*dst_pudp;
@@ -122,7 +123,7 @@ static int copy_pud(p4d_t *dst_p4dp, p4d_t *src_p4dp, unsigned long start,unsignedlongaddr=start;if(p4d_none(READ_ONCE(*dst_p4dp))){-dst_pudp=(pud_t*)get_safe_page(GFP_ATOMIC);+dst_pudp=trans_alloc(info);if(!dst_pudp)return-ENOMEM;p4d_populate(&init_mm,dst_p4dp,dst_pudp);
@@ -137,7 +138,7 @@ static int copy_pud(p4d_t *dst_p4dp, p4d_t *src_p4dp, unsigned long start,if(pud_none(pud))continue;if(pud_table(pud)){-if(copy_pmd(dst_pudp,src_pudp,addr,next))+if(copy_pmd(info,dst_pudp,src_pudp,addr,next))return-ENOMEM;}else{set_pud(dst_pudp,
@@ -148,7 +149,8 @@ static int copy_pud(p4d_t *dst_p4dp, p4d_t *src_p4dp, unsigned long start,return0;}-staticintcopy_p4d(pgd_t*dst_pgdp,pgd_t*src_pgdp,unsignedlongstart,+staticintcopy_p4d(structtrans_pgd_info*info,pgd_t*dst_pgdp,+pgd_t*src_pgdp,unsignedlongstart,unsignedlongend){p4d_t*dst_p4dp;
@@ -162,15 +164,15 @@ static int copy_p4d(pgd_t *dst_pgdp, pgd_t *src_pgdp, unsigned long start,next=p4d_addr_end(addr,end);if(p4d_none(READ_ONCE(*src_p4dp)))continue;-if(copy_pud(dst_p4dp,src_p4dp,addr,next))+if(copy_pud(info,dst_p4dp,src_p4dp,addr,next))return-ENOMEM;}while(dst_p4dp++,src_p4dp++,addr=next,addr!=end);return0;}-staticintcopy_page_tables(pgd_t*dst_pgdp,unsignedlongstart,-unsignedlongend)+staticintcopy_page_tables(structtrans_pgd_info*info,pgd_t*dst_pgdp,+unsignedlongstart,unsignedlongend){unsignedlongnext;unsignedlongaddr=start;
@@ -181,25 +183,34 @@ static int copy_page_tables(pgd_t *dst_pgdp, unsigned long start,next=pgd_addr_end(addr,end);if(pgd_none(READ_ONCE(*src_pgdp)))continue;-if(copy_p4d(dst_pgdp,src_pgdp,addr,next))+if(copy_p4d(info,dst_pgdp,src_pgdp,addr,next))return-ENOMEM;}while(dst_pgdp++,src_pgdp++,addr=next,addr!=end);return0;}-inttrans_pgd_create_copy(pgd_t**dst_pgdp,unsignedlongstart,-unsignedlongend)+/*+*Createtrans_pgdandcopylinearmap.+*info:containsallocatoranditsargument+*dst_pgdp:newpagetablethatiscreated,andtowhichmapiscopied.+*start:Startoftheinterval(inclusive).+*end:Endoftheinterval(exclusive).+*+*Returns0onsuccess,and-ENOMEMonfailure.+*/+inttrans_pgd_create_copy(structtrans_pgd_info*info,pgd_t**dst_pgdp,+unsignedlongstart,unsignedlongend){intrc;-pgd_t*trans_pgd=(pgd_t*)get_safe_page(GFP_ATOMIC);+pgd_t*trans_pgd=trans_alloc(info);if(!trans_pgd){pr_err("Failed to allocate memory for temporary page tables.\n");return-ENOMEM;}-rc=copy_page_tables(trans_pgd,start,end);+rc=copy_page_tables(info,trans_pgd,start,end);if(!rc)*dst_pgdp=trans_pgd;
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-25 19:44:31
x0 will contain the only argument to arm64_relocate_new_kernel; don't
use it as a temp. Reassigned registers to free-up x0 so we won't need
to copy argument, and can use it at the beginning and at the end of the
function.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: James Morse <james.morse@arm.com>
---
arch/arm64/kernel/relocate_kernel.S | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-25 19:45:18
Currently, relocation code declares start and end variables
which are used to compute it size.
The better way to do this is to use ld script incited, and put relocation
function in its own section.
Soon, relocation function will share the same page with EL2 vectors. So,
proper marking is needed.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/include/asm/kexec.h | 4 ++++
arch/arm64/include/asm/sections.h | 1 +
arch/arm64/kernel/machine_kexec.c | 17 ++++++++---------
arch/arm64/kernel/relocate_kernel.S | 15 ++-------------
arch/arm64/kernel/vmlinux.lds.S | 19 +++++++++++++++++++
5 files changed, 34 insertions(+), 22 deletions(-)
@@ -20,13 +20,10 @@#include<asm/mmu.h>#include<asm/mmu_context.h>#include<asm/page.h>+#include<asm/sections.h>#include"cpu-reset.h"-/* Global variables for the arm64_relocate_new_kernel routine. */-externconstunsignedchararm64_relocate_new_kernel[];-externconstunsignedlongarm64_relocate_new_kernel_size;-/***kexec_image_info-Fordebuggingoutput.*/
@@ -78,13 +75,15 @@ int machine_kexec_post_load(struct kimage *kimage){void*reloc_code=page_to_virt(kimage->control_code_page);structkern_reloc_arg*kern_reloc_arg=kexec_page_alloc(kimage);+longfunc_offset,reloc_size;if(!kern_reloc_arg)return-ENOMEM;-memcpy(reloc_code,arm64_relocate_new_kernel,-arm64_relocate_new_kernel_size);-kimage->arch.kern_reloc=__pa(reloc_code);+func_offset=arm64_relocate_new_kernel-__relocate_new_kernel_start;+reloc_size=__relocate_new_kernel_end-__relocate_new_kernel_start;+memcpy(reloc_code,__relocate_new_kernel_start,reloc_size);+kimage->arch.kern_reloc=__pa(reloc_code)+func_offset;kimage->arch.kern_reloc_arg=__pa(kern_reloc_arg);kern_reloc_arg->head=kimage->head;kern_reloc_arg->entry_addr=kimage->start;
@@ -92,9 +91,9 @@ int machine_kexec_post_load(struct kimage *kimage)kexec_image_info(kimage);/* Flush the reloc_code in preparation for its execution. */-__flush_dcache_area(reloc_code,arm64_relocate_new_kernel_size);+__flush_dcache_area(reloc_code,reloc_size);flush_icache_range((uintptr_t)reloc_code,(uintptr_t)reloc_code+-arm64_relocate_new_kernel_size);+reloc_size);__flush_dcache_area(kern_reloc_arg,sizeof(structkern_reloc_arg));return0;
@@ -316,3 +328,10 @@ ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) == PAGE_SIZE,*Ifpaddingisappliedbefore.head.text,virt<->physconversionswillfail.*/ASSERT(_text==KIMAGE_VADDR,"HEAD is misaligned")++#ifdef CONFIG_KEXEC_CORE+/*kexecrelocationcodeshouldfitintooneKEXEC_CONTROL_PAGE_SIZE*/+ASSERT(__relocate_new_kernel_end-(__relocate_new_kernel_start&~(SZ_4K-1))+<=SZ_4K,"kexec relocation code is too big or misaligned")+ASSERT(KEXEC_CONTROL_PAGE_SIZE>=SZ_4K,"KEXEC_CONTROL_PAGE_SIZE is brokern")+#endif
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 01:24:42
Configure a page table located in kexec-safe memory that has
the following mappings:
1. identity mapping for text of relocation function with executable
permission.
2. va mappings for all source ranges
3. va mappings for all destination ranges.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/include/asm/kexec.h | 12 ++++
arch/arm64/kernel/asm-offsets.c | 6 ++
arch/arm64/kernel/machine_kexec.c | 91 ++++++++++++++++++++++++++++++-
3 files changed, 108 insertions(+), 1 deletion(-)
@@ -95,6 +176,14 @@ int machine_kexec_post_load(struct kimage *kimage)if(is_hyp_mode_available()&&!is_kernel_in_hyp_mode())kern_reloc_arg->el2_vector=__pa(reloc_code)+vector_offset;+/*+*Ifrelocationisnotneeded,wedonotneedtoenableMMUin+*relocationroutine,thereforedonotcreatepagetablesfor+*scenariossuchascrashkernel+*/+if(!(kimage->head&IND_DONE))+rc=mmu_relocate_setup(kimage,reloc_code,kern_reloc_arg);+kexec_image_info(kimage);/* Flush the reloc_code in preparation for its execution. */
@@ -103,7 +192,7 @@ int machine_kexec_post_load(struct kimage *kimage)reloc_size);__flush_dcache_area(kern_reloc_arg,sizeof(structkern_reloc_arg));-return0;+returnrc;}/**
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 10:12:47
Currently, dtb_mem is enabled only when CONFIG_KEXEC_FILE is
enabled. This adds ugly ifdefs to c files.
Always enabled dtb_mem, when it is not used, it is NULL.
Change the dtb_mem to phys_addr_t, as it is a physical address.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: James Morse <james.morse@arm.com>
---
arch/arm64/include/asm/kexec.h | 4 ++--
arch/arm64/kernel/machine_kexec.c | 6 +-----
2 files changed, 3 insertions(+), 7 deletions(-)
@@ -204,11 +204,7 @@ void machine_kexec(struct kimage *kimage)*Inkexec_filecase,thekernelstartsdirectlywithoutpurgatory.*/cpu_soft_restart(reboot_code_buffer_phys,kimage->head,kimage->start,-#ifdef CONFIG_KEXEC_FILE-kimage->arch.dtb_mem);-#else-0);-#endif+kimage->arch.dtb_mem);BUG();/* Should never get here. */}
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 10:12:51
There should be p4dp used when p4d page is allocated.
This is not a functional issue, but for the logical correctness this
should be fixed.
Fixes: e9f6376858b9 ("arm64: add support for folded p4d page tables")
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/kernel/hibernate.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 10:13:11
kexec is going to use a different allocator, so make
trans_pgd_map_page to accept allocator as an argument, and also
kexec is going to use a different map protection, so also pass
it via argument.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Matthias Brugger <mbrugger@suse.com>
---
arch/arm64/include/asm/trans_pgd.h | 19 +++++++++++++++++--
arch/arm64/kernel/hibernate.c | 12 +++++++++++-
arch/arm64/mm/trans_pgd.c | 30 ++++++++++++++++++++++--------
3 files changed, 50 insertions(+), 11 deletions(-)
@@ -201,9 +206,18 @@ int trans_pgd_create_copy(pgd_t **dst_pgdp, unsigned long start,returnrc;}-inttrans_pgd_map_page(pgd_t*trans_pgd,void*page,-unsignedlongdst_addr,-pgprot_tpgprot)+/*+*Addmapentrytotrans_pgdforabase-sizepageatPTElevel.+*info:containsallocatoranditsargument+*trans_pgd:pagetableinwhichnewmapisadded.+*page:pagetobemapped.+*dst_addr:newVAaddressforthepage+*pgprot:protectionforthepage.+*+*Returns0onsuccess,and-ENOMEMonfailure.+*/+inttrans_pgd_map_page(structtrans_pgd_info*info,pgd_t*trans_pgd,+void*page,unsignedlongdst_addr,pgprot_tpgprot){pgd_t*pgdp;p4d_t*p4dp;
@@ -213,7 +227,7 @@ int trans_pgd_map_page(pgd_t *trans_pgd, void *page,pgdp=pgd_offset_pgd(trans_pgd,dst_addr);if(pgd_none(READ_ONCE(*pgdp))){-p4dp=(void*)get_safe_page(GFP_ATOMIC);+p4dp=trans_alloc(info);if(!pgdp)return-ENOMEM;pgd_populate(&init_mm,pgdp,p4dp);
@@ -221,7 +235,7 @@ int trans_pgd_map_page(pgd_t *trans_pgd, void *page,p4dp=p4d_offset(pgdp,dst_addr);if(p4d_none(READ_ONCE(*p4dp))){-pudp=(void*)get_safe_page(GFP_ATOMIC);+pudp=trans_alloc(info);if(!pudp)return-ENOMEM;p4d_populate(&init_mm,p4dp,pudp);
@@ -229,7 +243,7 @@ int trans_pgd_map_page(pgd_t *trans_pgd, void *page,pudp=pud_offset(p4dp,dst_addr);if(pud_none(READ_ONCE(*pudp))){-pmdp=(void*)get_safe_page(GFP_ATOMIC);+pmdp=trans_alloc(info);if(!pmdp)return-ENOMEM;pud_populate(&init_mm,pudp,pmdp);
@@ -237,14 +251,14 @@ int trans_pgd_map_page(pgd_t *trans_pgd, void *page,pmdp=pmd_offset(pudp,dst_addr);if(pmd_none(READ_ONCE(*pmdp))){-ptep=(void*)get_safe_page(GFP_ATOMIC);+ptep=trans_alloc(info);if(!ptep)return-ENOMEM;pmd_populate_kernel(&init_mm,pmdp,ptep);}ptep=pte_offset_kernel(pmdp,dst_addr);-set_pte(ptep,pfn_pte(virt_to_pfn(page),PAGE_KERNEL_EXEC));+set_pte(ptep,pfn_pte(virt_to_pfn(page),pgprot));return0;}
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 10:13:17
Now, that we abstracted the required functions move them to a new home.
Later, we will generalize these function in order to be useful outside
of hibernation.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: James Morse <james.morse@arm.com>
---
arch/arm64/Kconfig | 4 +
arch/arm64/include/asm/trans_pgd.h | 21 +++
arch/arm64/kernel/hibernate.c | 228 +-------------------------
arch/arm64/mm/Makefile | 1 +
arch/arm64/mm/trans_pgd.c | 250 +++++++++++++++++++++++++++++
5 files changed, 277 insertions(+), 227 deletions(-)
create mode 100644 arch/arm64/include/asm/trans_pgd.h
create mode 100644 arch/arm64/mm/trans_pgd.c
@@ -178,54 +176,6 @@ int arch_hibernation_header_restore(void *addr)}EXPORT_SYMBOL(arch_hibernation_header_restore);-staticinttrans_pgd_map_page(pgd_t*trans_pgd,void*page,-unsignedlongdst_addr,-pgprot_tpgprot)-{-pgd_t*pgdp;-p4d_t*p4dp;-pud_t*pudp;-pmd_t*pmdp;-pte_t*ptep;--pgdp=pgd_offset_pgd(trans_pgd,dst_addr);-if(pgd_none(READ_ONCE(*pgdp))){-p4dp=(void*)get_safe_page(GFP_ATOMIC);-if(!pgdp)-return-ENOMEM;-pgd_populate(&init_mm,pgdp,p4dp);-}--p4dp=p4d_offset(pgdp,dst_addr);-if(p4d_none(READ_ONCE(*p4dp))){-pudp=(void*)get_safe_page(GFP_ATOMIC);-if(!pudp)-return-ENOMEM;-p4d_populate(&init_mm,p4dp,pudp);-}--pudp=pud_offset(p4dp,dst_addr);-if(pud_none(READ_ONCE(*pudp))){-pmdp=(void*)get_safe_page(GFP_ATOMIC);-if(!pmdp)-return-ENOMEM;-pud_populate(&init_mm,pudp,pmdp);-}--pmdp=pmd_offset(pudp,dst_addr);-if(pmd_none(READ_ONCE(*pmdp))){-ptep=(void*)get_safe_page(GFP_ATOMIC);-if(!ptep)-return-ENOMEM;-pmd_populate_kernel(&init_mm,pmdp,ptep);-}--ptep=pte_offset_kernel(pmdp,dst_addr);-set_pte(ptep,pfn_pte(virt_to_pfn(page),PAGE_KERNEL_EXEC));--return0;-}-/**Copieslengthbytes,startingatsrc_startintoannewpage,*performcachemaintenance,thenmapsitatthespecifiedaddresslow
@@ -462,182 +412,6 @@ int swsusp_arch_suspend(void)returnret;}-staticvoid_copy_pte(pte_t*dst_ptep,pte_t*src_ptep,unsignedlongaddr)-{-pte_tpte=READ_ONCE(*src_ptep);--if(pte_valid(pte)){-/*-*Resumewilloverwriteareasthatmaybemarked-*readonly(code,rodata).CleartheRDONLYbitfrom-*thetemporarymappingsweuseduringrestore.-*/-set_pte(dst_ptep,pte_mkwrite(pte));-}elseif(debug_pagealloc_enabled()&&!pte_none(pte)){-/*-*debug_pageallocwillremovedthePTE_VALIDbitif-*thepageisn'tinusebytheresumekernel.Itmayhave-*beeninusebytheoriginalkernel,inwhichcaseweneed-*toputitbackinourcopytodotherestore.-*-*Beforemarkingthisentryvalid,checkthepfnshould-*bemapped.-*/-BUG_ON(!pfn_valid(pte_pfn(pte)));--set_pte(dst_ptep,pte_mkpresent(pte_mkwrite(pte)));-}-}--staticintcopy_pte(pmd_t*dst_pmdp,pmd_t*src_pmdp,unsignedlongstart,-unsignedlongend)-{-pte_t*src_ptep;-pte_t*dst_ptep;-unsignedlongaddr=start;--dst_ptep=(pte_t*)get_safe_page(GFP_ATOMIC);-if(!dst_ptep)-return-ENOMEM;-pmd_populate_kernel(&init_mm,dst_pmdp,dst_ptep);-dst_ptep=pte_offset_kernel(dst_pmdp,start);--src_ptep=pte_offset_kernel(src_pmdp,start);-do{-_copy_pte(dst_ptep,src_ptep,addr);-}while(dst_ptep++,src_ptep++,addr+=PAGE_SIZE,addr!=end);--return0;-}--staticintcopy_pmd(pud_t*dst_pudp,pud_t*src_pudp,unsignedlongstart,-unsignedlongend)-{-pmd_t*src_pmdp;-pmd_t*dst_pmdp;-unsignedlongnext;-unsignedlongaddr=start;--if(pud_none(READ_ONCE(*dst_pudp))){-dst_pmdp=(pmd_t*)get_safe_page(GFP_ATOMIC);-if(!dst_pmdp)-return-ENOMEM;-pud_populate(&init_mm,dst_pudp,dst_pmdp);-}-dst_pmdp=pmd_offset(dst_pudp,start);--src_pmdp=pmd_offset(src_pudp,start);-do{-pmd_tpmd=READ_ONCE(*src_pmdp);--next=pmd_addr_end(addr,end);-if(pmd_none(pmd))-continue;-if(pmd_table(pmd)){-if(copy_pte(dst_pmdp,src_pmdp,addr,next))-return-ENOMEM;-}else{-set_pmd(dst_pmdp,-__pmd(pmd_val(pmd)&~PMD_SECT_RDONLY));-}-}while(dst_pmdp++,src_pmdp++,addr=next,addr!=end);--return0;-}--staticintcopy_pud(p4d_t*dst_p4dp,p4d_t*src_p4dp,unsignedlongstart,-unsignedlongend)-{-pud_t*dst_pudp;-pud_t*src_pudp;-unsignedlongnext;-unsignedlongaddr=start;--if(p4d_none(READ_ONCE(*dst_p4dp))){-dst_pudp=(pud_t*)get_safe_page(GFP_ATOMIC);-if(!dst_pudp)-return-ENOMEM;-p4d_populate(&init_mm,dst_p4dp,dst_pudp);-}-dst_pudp=pud_offset(dst_p4dp,start);--src_pudp=pud_offset(src_p4dp,start);-do{-pud_tpud=READ_ONCE(*src_pudp);--next=pud_addr_end(addr,end);-if(pud_none(pud))-continue;-if(pud_table(pud)){-if(copy_pmd(dst_pudp,src_pudp,addr,next))-return-ENOMEM;-}else{-set_pud(dst_pudp,-__pud(pud_val(pud)&~PUD_SECT_RDONLY));-}-}while(dst_pudp++,src_pudp++,addr=next,addr!=end);--return0;-}--staticintcopy_p4d(pgd_t*dst_pgdp,pgd_t*src_pgdp,unsignedlongstart,-unsignedlongend)-{-p4d_t*dst_p4dp;-p4d_t*src_p4dp;-unsignedlongnext;-unsignedlongaddr=start;--dst_p4dp=p4d_offset(dst_pgdp,start);-src_p4dp=p4d_offset(src_pgdp,start);-do{-next=p4d_addr_end(addr,end);-if(p4d_none(READ_ONCE(*src_p4dp)))-continue;-if(copy_pud(dst_p4dp,src_p4dp,addr,next))-return-ENOMEM;-}while(dst_p4dp++,src_p4dp++,addr=next,addr!=end);--return0;-}--staticintcopy_page_tables(pgd_t*dst_pgdp,unsignedlongstart,-unsignedlongend)-{-unsignedlongnext;-unsignedlongaddr=start;-pgd_t*src_pgdp=pgd_offset_k(start);--dst_pgdp=pgd_offset_pgd(dst_pgdp,start);-do{-next=pgd_addr_end(addr,end);-if(pgd_none(READ_ONCE(*src_pgdp)))-continue;-if(copy_p4d(dst_pgdp,src_pgdp,addr,next))-return-ENOMEM;-}while(dst_pgdp++,src_pgdp++,addr=next,addr!=end);--return0;-}--staticinttrans_pgd_create_copy(pgd_t**dst_pgdp,unsignedlongstart,-unsignedlongend)-{-intrc;-pgd_t*trans_pgd=(pgd_t*)get_safe_page(GFP_ATOMIC);--if(!trans_pgd){-pr_err("Failed to allocate memory for temporary page tables.\n");-return-ENOMEM;-}--rc=copy_page_tables(trans_pgd,start,end);-if(!rc)-*dst_pgdp=trans_pgd;--returnrc;-}-/**SetupthenResumefromthehibernateimageusingswsusp_arch_suspend_exit().*
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 10:13:59
trans_pgd_* should be independent from mm context because the tables that
are created by this code are used when there are no mm context around, as
it is between kernels. Simply replace mm_init's with NULL.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Acked-by: James Morse <james.morse@arm.com>
---
arch/arm64/mm/trans_pgd.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 10:15:40
In preparation to bigger changes to arm64_relocate_new_kernel that would
enable this function to do MMU backed memory copy, do few clean-ups and
optimizations. These include:
1. Call raw_dcache_line_size() only when relocation is actually going to
happen. i.e. kdump type kexec, does not need it.
2. copy_page(dest, src, tmps...) increments dest and src by PAGE_SIZE, so
no need to store dest prior to calling copy_page and increment it
after. Also, src is not used after a copy, not need to copy either.
3. For consistency use comment on the same line with instruction when it
describes the instruction itself.
4. Some comment corrections
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/kernel/relocate_kernel.S | 36 +++++++----------------------
1 file changed, 8 insertions(+), 28 deletions(-)
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 10:15:40
Currently, kernel relocation function is configured in machine_kexec()
at the time of kexec reboot by using control_code_page.
This operation, however, is more logical to be done during kexec_load,
and thus remove from reboot time. Move, setup of this function to
newly added machine_kexec_post_load().
Because once MMU is enabled, kexec control page will contain more than
relocation kernel, but also vector table, add pointer to the actual
function within this page arch.kern_reloc. Currently, it equals to the
beginning of page, we will add offsets later, when vector table is
added.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: James Morse <james.morse@arm.com>
---
arch/arm64/include/asm/kexec.h | 1 +
arch/arm64/kernel/machine_kexec.c | 46 +++++++++++++------------------
2 files changed, 20 insertions(+), 27 deletions(-)
@@ -58,6 +59,22 @@ void machine_kexec_cleanup(struct kimage *kimage)/* Empty routine needed to avoid build errors. */}+intmachine_kexec_post_load(structkimage*kimage)+{+void*reloc_code=page_to_virt(kimage->control_code_page);++memcpy(reloc_code,arm64_relocate_new_kernel,+arm64_relocate_new_kernel_size);+kimage->arch.kern_reloc=__pa(reloc_code);++/* Flush the reloc_code in preparation for its execution. */+__flush_dcache_area(reloc_code,arm64_relocate_new_kernel_size);+flush_icache_range((uintptr_t)reloc_code,(uintptr_t)reloc_code++arm64_relocate_new_kernel_size);++return0;+}+/***machine_kexec_prepare-Prepareforakexecreboot.*
@@ -155,31 +170,8 @@ void machine_kexec(struct kimage *kimage)WARN(in_kexec_crash&&(stuck_cpus||smp_crash_stop_failed()),"Some CPUs may be stale, kdump will be unreliable.\n");-reboot_code_buffer_phys=page_to_phys(kimage->control_code_page);-reboot_code_buffer=phys_to_virt(reboot_code_buffer_phys);-kexec_image_info(kimage);-/*-*Copyarm64_relocate_new_kerneltothereboot_code_bufferforuse-*afterthekernelisshutdown.-*/-memcpy(reboot_code_buffer,arm64_relocate_new_kernel,-arm64_relocate_new_kernel_size);--/* Flush the reboot_code_buffer in preparation for its execution. */-__flush_dcache_area(reboot_code_buffer,arm64_relocate_new_kernel_size);--/*-*Althoughwe'vekilledoffthesecondaryCPUs,wedon'tupdate-*theonlinemaskifwe'rehandlingacrashkernelandconsequently-*needtoavoidflush_icache_range(),whichwillattempttoIPI-*theofflineCPUs.Therefore,wemustusethe__*varianthere.-*/-__flush_icache_range((uintptr_t)reboot_code_buffer,-(uintptr_t)reboot_code_buffer+-arm64_relocate_new_kernel_size);-/* Flush the kimage list and its buffers. */kexec_list_flush(kimage);
@@ -203,7 +195,7 @@ void machine_kexec(struct kimage *kimage)*userspace(kexec-tools).*Inkexec_filecase,thekernelstartsdirectlywithoutpurgatory.*/-cpu_soft_restart(reboot_code_buffer_phys,kimage->head,kimage->start,+cpu_soft_restart(kimage->arch.kern_reloc,kimage->head,kimage->start,kimage->arch.dtb_mem);BUG();/* Should never get here. */
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 10:15:40
Currently, kexec relocation function (arm64_relocate_new_kernel) accepts
the following arguments:
head: start of array that contains relocation information.
entry: entry point for new kernel or purgatory.
dtb_mem: first and only argument to entry.
The number of arguments cannot be easily expended, because this
function is also called from HVC_SOFT_RESTART, which preserves only
three arguments (hypervisor abi). And, also arm64_relocate_new_kernel is
written in assembly but called without stack, thus no place to move extra
arguments to free registers.
Soon, we will need to pass more arguments: once we enable MMU we
will need to pass information about page tables.
Add a new struct: kern_reloc_arg, and place it in kexec safe page (i.e
memory that is not overwritten during relocation).
Thus, make arm64_relocate_new_kernel to only take one argument, that
contains all the needed information.
Note:
Another benefit of allowing this function to accept more arguments, is that
kernel can actually accept up to 4 arguments (x0-x3), however currently
only one is used, but if in the future we will need for more (for example,
pass information about when previous kernel exited to have a precise
measurement in time spent in purgatory), we won't be easilty do that
if arm64_relocate_new_kernel can't accept more arguments.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/include/asm/kexec.h | 18 ++++++++++++++++++
arch/arm64/kernel/asm-offsets.c | 9 +++++++++
arch/arm64/kernel/cpu-reset.S | 11 +++--------
arch/arm64/kernel/cpu-reset.h | 8 +++-----
arch/arm64/kernel/machine_kexec.c | 27 +++++++++++++++++++++++++--
arch/arm64/kernel/relocate_kernel.S | 21 ++++++++-------------
6 files changed, 66 insertions(+), 28 deletions(-)
@@ -59,19 +60,42 @@ void machine_kexec_cleanup(struct kimage *kimage)/* Empty routine needed to avoid build errors. */}+/* Allocates pages for kexec page table */+staticvoid*kexec_page_alloc(void*arg)+{+structkimage*kimage=(structkimage*)arg;+structpage*page=kimage_alloc_control_pages(kimage,0);++if(!page)+returnNULL;++memset(page_address(page),0,PAGE_SIZE);++returnpage_address(page);+}+intmachine_kexec_post_load(structkimage*kimage){void*reloc_code=page_to_virt(kimage->control_code_page);+structkern_reloc_arg*kern_reloc_arg=kexec_page_alloc(kimage);++if(!kern_reloc_arg)+return-ENOMEM;memcpy(reloc_code,arm64_relocate_new_kernel,arm64_relocate_new_kernel_size);kimage->arch.kern_reloc=__pa(reloc_code);+kimage->arch.kern_reloc_arg=__pa(kern_reloc_arg);+kern_reloc_arg->head=kimage->head;+kern_reloc_arg->entry_addr=kimage->start;+kern_reloc_arg->kern_arg0=kimage->arch.dtb_mem;kexec_image_info(kimage);/* Flush the reloc_code in preparation for its execution. */__flush_dcache_area(reloc_code,arm64_relocate_new_kernel_size);flush_icache_range((uintptr_t)reloc_code,(uintptr_t)reloc_code+arm64_relocate_new_kernel_size);+__flush_dcache_area(kern_reloc_arg,sizeof(structkern_reloc_arg));return0;}
@@ -192,8 +216,7 @@ void machine_kexec(struct kimage *kimage)*userspace(kexec-tools).*Inkexec_filecase,thekernelstartsdirectlywithoutpurgatory.*/-cpu_soft_restart(kimage->arch.kern_reloc,kimage->head,kimage->start,-kimage->arch.dtb_mem);+cpu_soft_restart(kimage->arch.kern_reloc,kimage->arch.kern_reloc_arg);BUG();/* Should never get here. */}
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 12:29:39
I forgot to make changes to arch/arm64/Kconfig. The correct patch is
below.
---
From a2bc374320d7c7efd3c40644ad3d6d59a024b301 Mon Sep 17 00:00:00 2001
From: Pavel Tatashin <pasha.tatashin@soleen.com>
Date: Mon, 29 Jul 2019 21:24:25 -0400
Subject: [PATCH v10 16/18] arm64: kexec: configure trans_pgd page table for
kexec
Configure a page table located in kexec-safe memory that has
the following mappings:
1. identity mapping for text of relocation function with executable
permission.
2. va mappings for all source ranges
3. va mappings for all destination ranges.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/Kconfig | 2 +-
arch/arm64/include/asm/kexec.h | 12 ++++
arch/arm64/kernel/asm-offsets.c | 6 ++
arch/arm64/kernel/machine_kexec.c | 91 ++++++++++++++++++++++++++++++-
4 files changed, 109 insertions(+), 2 deletions(-)
@@ -95,6 +176,14 @@ int machine_kexec_post_load(struct kimage *kimage)if(is_hyp_mode_available()&&!is_kernel_in_hyp_mode())kern_reloc_arg->el2_vector=__pa(reloc_code)+vector_offset;+/*+*Ifrelocationisnotneeded,wedonotneedtoenableMMUin+*relocationroutine,thereforedonotcreatepagetablesfor+*scenariossuchascrashkernel+*/+if(!(kimage->head&IND_DONE))+rc=mmu_relocate_setup(kimage,reloc_code,kern_reloc_arg);+kexec_image_info(kimage);/* Flush the reloc_code in preparation for its execution. */
@@ -103,7 +192,7 @@ int machine_kexec_post_load(struct kimage *kimage)reloc_size);__flush_dcache_area(kern_reloc_arg,sizeof(structkern_reloc_arg));-return0;+returnrc;}/**
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 12:39:36
Currently, kexec_image_info() is called during load time, and
right before kernel is being kexec'ed. There is no need to do both.
So, call it only once when segments are loaded and the physical
location of page with copy of arm64_relocate_new_kernel is known.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Acked-by: James Morse <james.morse@arm.com>
---
arch/arm64/kernel/machine_kexec.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
@@ -66,6 +66,7 @@ int machine_kexec_post_load(struct kimage *kimage)memcpy(reloc_code,arm64_relocate_new_kernel,arm64_relocate_new_kernel_size);kimage->arch.kern_reloc=__pa(reloc_code);+kexec_image_info(kimage);/* Flush the reloc_code in preparation for its execution. */__flush_dcache_area(reloc_code,arm64_relocate_new_kernel_size);
@@ -84,8 +85,6 @@ int machine_kexec_post_load(struct kimage *kimage)*/intmachine_kexec_prepare(structkimage*kimage){-kexec_image_info(kimage);-if(kimage->type!=KEXEC_TYPE_CRASH&&cpus_are_stuck_in_kernel()){pr_err("Can't kexec: CPUs are stuck in the kernel.\n");return-EBUSY;
@@ -170,8 +169,6 @@ void machine_kexec(struct kimage *kimage)WARN(in_kexec_crash&&(stuck_cpus||smp_crash_stop_failed()),"Some CPUs may be stale, kdump will be unreliable.\n");-kexec_image_info(kimage);-/* Flush the kimage list and its buffers. */kexec_list_flush(kimage);
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-26 12:40:23
From: James Morse <james.morse@arm.com>
To resume from hibernate, the contents of memory are restored from
the swap image. This may overwrite any page, including the running
kernel and its page tables.
Hibernate copies the code it uses to do the restore into a single
page that it knows won't be overwritten, and maps it with page tables
built from pages that won't be overwritten.
Today the address it uses for this mapping is arbitrary, but to allow
kexec to reuse this code, it needs to be idmapped. To idmap the page
we must avoid the kernel helpers that have VA_BITS baked in.
Convert create_single_mapping() to take a single PA, and idmap it.
The page tables are built in the reverse order to normal using
pfn_pte() to stir in any bits between 52:48. T0SZ is always increased
to cover 48bits, or 52 if the copy code has bits 52:48 in its PA.
Signed-off-by: James Morse <james.morse@arm.com>
[Adopted the original patch from James to trans_pgd interface, so it can be
commonly used by both Kexec and Hibernate. Some minor clean-ups.]
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Link: https://lore.kernel.org/linux-arm-kernel/20200115143322.214247-4-james.morse@arm.com/
---
arch/arm64/include/asm/trans_pgd.h | 3 ++
arch/arm64/kernel/hibernate.c | 32 +++++++------------
arch/arm64/mm/trans_pgd.c | 49 ++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 21 deletions(-)
@@ -203,7 +202,8 @@ static int create_safe_exec_page(void *src_start, size_t length,};void*page=(void*)get_safe_page(GFP_ATOMIC);-pgd_t*trans_pgd;+phys_addr_ttrans_ttbr0;+unsignedlongt0sz;intrc;if(!page)
@@ -211,13 +211,7 @@ static int create_safe_exec_page(void *src_start, size_t length,memcpy(page,src_start,length);__flush_icache_range((unsignedlong)page,(unsignedlong)page+length);--trans_pgd=(void*)get_safe_page(GFP_ATOMIC);-if(!trans_pgd)-return-ENOMEM;--rc=trans_pgd_map_page(&trans_info,trans_pgd,page,dst_addr,-PAGE_KERNEL_EXEC);+rc=trans_pgd_idmap_page(&trans_info,&trans_ttbr0,&t0sz,page);if(rc)returnrc;
@@ -230,12 +224,15 @@ static int create_safe_exec_page(void *src_start, size_t length,*page,butTLBsmaycontainstaleASID-taggedentries(e.g.forEFI*runtimeservices),whileforauserspace-driventest_resumecycleit*pointstouserspacepagetables(andwemustpointitatazeropage-*ourselves).Elsewhereweonly(un)installtheidmapwithpreemption-*disabled,soT0SZshouldbeasrequiredregardless.+*ourselves).+*+*WechangeT0SZaspartofinstallingtheidmap.Thisisundoneby+*cpu_uninstall_idmap()in__cpu_suspend_exit().*/cpu_set_reserved_ttbr0();local_flush_tlb_all();-write_sysreg(phys_to_ttbr(virt_to_phys(trans_pgd)),ttbr0_el1);+__cpu_set_tcr_t0sz(t0sz);+write_sysreg(trans_ttbr0,ttbr0_el1);isb();*phys_dst_addr=virt_to_phys(page);
@@ -434,7 +431,6 @@ int swsusp_arch_resume(void)void*zero_page;size_texit_size;pgd_t*tmp_pg_dir;-phys_addr_tphys_hibernate_exit;void__noreturn(*hibernate_exit)(phys_addr_t,phys_addr_t,void*,void*,phys_addr_t,phys_addr_t);structtrans_pgd_infotrans_info={
@@ -462,19 +458,13 @@ int swsusp_arch_resume(void)return-ENOMEM;}-/*-*Locatetheexitcodeinthebottom-but-onepage,sothat*NULL-*stillhasdisastrousaffects.-*/-hibernate_exit=(void*)PAGE_SIZE;exit_size=__hibernate_exit_text_end-__hibernate_exit_text_start;/**Copyswsusp_arch_suspend_exit()toasafepage.Thiswillgenerate*anewsetofttbr0pagetablesandloadthem.*/rc=create_safe_exec_page(__hibernate_exit_text_start,exit_size,-(unsignedlong)hibernate_exit,-&phys_hibernate_exit);+(phys_addr_t*)&hibernate_exit);if(rc){pr_err("Failed to create safe executable page for hibernate_exit code.\n");returnrc;
@@ -493,7 +483,7 @@ int swsusp_arch_resume(void)*WecanskipthisstepifwebootedatEL1,orarerunningwithVHE.*/if(el2_reset_needed()){-phys_addr_tel2_vectors=phys_hibernate_exit;/* base */+phys_addr_tel2_vectors=(phys_addr_t)hibernate_exit;el2_vectors+=hibernate_el2_vectors-__hibernate_exit_text_start;/* offset */
From: Will Deacon <will@kernel.org> Date: 2021-01-27 08:25:52
On Tue, Jan 26, 2021 at 06:05:10PM -0500, Pavel Tatashin wrote:
On Tue, Jan 26, 2021 at 5:58 PM Will Deacon [off-list ref] wrote:
quoted
Hi Pavel,
On Mon, Jan 25, 2021 at 02:19:05PM -0500, Pavel Tatashin wrote:
quoted
Changelog:
v10:
- Addressed a lot of comments form James Morse and from Marc Zyngier
- Added review-by's
- Synchronized with mainline
This series has been doing the rounds for a while, but still isn't fully
reviewed. Would it help if I merged, e.g. the first 12 patches to reduce the
amount you have to repost?
Hi Will,
Yes, it would. The first 10 patches of this series were already merged
sometime ago:
a2c2e67923ec arm64: hibernate: add trans_pgd public functions
7ea4088938b7 arm64: hibernate: add PUD_SECT_RDONLY
13373f0e6580 arm64: hibernate: rename dst to page in create_safe_exec_page
a89d7ff933b0 arm64: hibernate: remove gotos as they are not needed
051a7a94aaa9 arm64: hibernate: use get_safe_page directly
d234332c2815 arm64: hibernate: pass the allocated pgdp to ttbr0
621516789ee6 arm64: kexec: make dtb_mem always enabled
3b54b743397e arm64: kexec: remove unnecessary debug prints
de68e4daea90 kexec: add machine_kexec_post_load()
d42cc530b18d kexec: quiet down kexec reboot
So, merging another ~12, would substantially help with getting
everything reviewed and merged.
Ok, great; I'll have a crack at that tomorrow, and thanks for persevering.
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-27 10:12:06
On Tue, Jan 26, 2021 at 5:58 PM Will Deacon [off-list ref] wrote:
Hi Pavel,
On Mon, Jan 25, 2021 at 02:19:05PM -0500, Pavel Tatashin wrote:
quoted
Changelog:
v10:
- Addressed a lot of comments form James Morse and from Marc Zyngier
- Added review-by's
- Synchronized with mainline
This series has been doing the rounds for a while, but still isn't fully
reviewed. Would it help if I merged, e.g. the first 12 patches to reduce the
amount you have to repost?
Hi Will,
Yes, it would. The first 10 patches of this series were already merged
sometime ago:
a2c2e67923ec arm64: hibernate: add trans_pgd public functions
7ea4088938b7 arm64: hibernate: add PUD_SECT_RDONLY
13373f0e6580 arm64: hibernate: rename dst to page in create_safe_exec_page
a89d7ff933b0 arm64: hibernate: remove gotos as they are not needed
051a7a94aaa9 arm64: hibernate: use get_safe_page directly
d234332c2815 arm64: hibernate: pass the allocated pgdp to ttbr0
621516789ee6 arm64: kexec: make dtb_mem always enabled
3b54b743397e arm64: kexec: remove unnecessary debug prints
de68e4daea90 kexec: add machine_kexec_post_load()
d42cc530b18d kexec: quiet down kexec reboot
So, merging another ~12, would substantially help with getting
everything reviewed and merged.
Thank you,
Pavel
From: Will Deacon <will@kernel.org> Date: 2021-01-27 10:35:47
Hi Pavel,
On Mon, Jan 25, 2021 at 02:19:05PM -0500, Pavel Tatashin wrote:
Changelog:
v10:
- Addressed a lot of comments form James Morse and from Marc Zyngier
- Added review-by's
- Synchronized with mainline
This series has been doing the rounds for a while, but still isn't fully
reviewed. Would it help if I merged, e.g. the first 12 patches to reduce the
amount you have to repost?
Will
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-27 16:15:03
On Wed, Jan 27, 2021 at 10:59 AM Will Deacon [off-list ref] wrote:
On Mon, 25 Jan 2021 14:19:05 -0500, Pavel Tatashin wrote:
quoted
Changelog:
v10:
- Addressed a lot of comments form James Morse and from Marc Zyngier
- Added review-by's
- Synchronized with mainline
[...]
Applied the first 12 patches to arm64 (for-next/kexec), thanks!
Great, thank you. I will resend the rest of the series based on your gate.
Pasha
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
I forgot to make changes to arch/arm64/Kconfig. The correct patch is
below.
---
From a2bc374320d7c7efd3c40644ad3d6d59a024b301 Mon Sep 17 00:00:00 2001
From: Pavel Tatashin <pasha.tatashin@soleen.com>
Date: Mon, 29 Jul 2019 21:24:25 -0400
Subject: [PATCH v10 16/18] arm64: kexec: configure trans_pgd page table for
kexec
Configure a page table located in kexec-safe memory that has
the following mappings:
1. identity mapping for text of relocation function with executable
permission.
2. va mappings for all source ranges
3. va mappings for all destination ranges.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/Kconfig | 2 +-
arch/arm64/include/asm/kexec.h | 12 ++++
arch/arm64/kernel/asm-offsets.c | 6 ++
arch/arm64/kernel/machine_kexec.c | 91 ++++++++++++++++++++++++++++++-
4 files changed, 109 insertions(+), 2 deletions(-)
@@ -95,6 +176,14 @@ int machine_kexec_post_load(struct kimage *kimage) if (is_hyp_mode_available() && !is_kernel_in_hyp_mode()) kern_reloc_arg->el2_vector = __pa(reloc_code) + vector_offset;+ /*+ * If relocation is not needed, we do not need to enable MMU in+ * relocation routine, therefore do not create page tables for+ * scenarios such as crash kernel+ */+ if (!(kimage->head & IND_DONE))+ rc = mmu_relocate_setup(kimage, reloc_code, kern_reloc_arg);+ kexec_image_info(kimage); /* Flush the reloc_code in preparation for its execution. */
From: Pavel Tatashin <pasha.tatashin@soleen.com> Date: 2021-01-27 16:49:12
On Wed, Jan 27, 2021 at 11:42 AM Tyler Hicks
[off-list ref] wrote:
On 2021-01-25 19:21:22, Pavel Tatashin wrote:
quoted
I forgot to make changes to arch/arm64/Kconfig. The correct patch is
below.
---
From a2bc374320d7c7efd3c40644ad3d6d59a024b301 Mon Sep 17 00:00:00 2001
From: Pavel Tatashin <pasha.tatashin@soleen.com>
Date: Mon, 29 Jul 2019 21:24:25 -0400
Subject: [PATCH v10 16/18] arm64: kexec: configure trans_pgd page table for
kexec
Configure a page table located in kexec-safe memory that has
the following mappings:
1. identity mapping for text of relocation function with executable
permission.
2. va mappings for all source ranges
3. va mappings for all destination ranges.
Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
---
arch/arm64/Kconfig | 2 +-
arch/arm64/include/asm/kexec.h | 12 ++++
arch/arm64/kernel/asm-offsets.c | 6 ++
arch/arm64/kernel/machine_kexec.c | 91 ++++++++++++++++++++++++++++++-
4 files changed, 109 insertions(+), 2 deletions(-)