* [RFC PATCH 0/3] arm64: hibernate: idmap the single page that holds the copy page routines @ 2020-01-15 14:33 James Morse 2020-01-15 14:33 ` [RFC PATCH 1/3] arm64: mm: Always update TCR_EL1 from __cpu_set_tcr_t0sz() James Morse ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: James Morse @ 2020-01-15 14:33 UTC (permalink / raw) To: Pavel Tatashin; +Cc: linux-arm-kernel Hello, Pavel T wants the kexec memory-copy to happen with the MMU on to take advantage of the caches. Hibernate pulls some tricks in this area which should be re-used. Kexec needs to turn the MMU off once its done, which needs to be done from the idmap. Hibernate's memory-copy code doesn't have this requirement, lets pretend we do. These patches are an RFC as I don't think they make sense on their own. The CC list is short for the same reason. This series adds another idmap that is created during resume from hibernate. Forcing the T0SZ up to at least 48 bits means this path can be tested on a 4K/39 or 64K/42 configuration. Kexec should be able to re-use his to map its copy routines low, using a 'safe' copy of the linear map in TTBR1. Tested on Juno and Seattle's magic 4K/39 configuration. I haven't been able to test this with the models 52bit PA support, but would be able to test it through kexec. Thanks, James Morse (3): arm64: mm: Always update TCR_EL1 from __cpu_set_tcr_t0sz() arm64: hibernate: Split create_safe_exec_page() and its mapping code arm64: hibernate: idmap the single page that holds the copy page routines arch/arm64/include/asm/mmu_context.h | 7 +- arch/arm64/kernel/hibernate.c | 146 ++++++++++++++------------- 2 files changed, 77 insertions(+), 76 deletions(-) -- 2.24.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 9+ messages in thread
* [RFC PATCH 1/3] arm64: mm: Always update TCR_EL1 from __cpu_set_tcr_t0sz() 2020-01-15 14:33 [RFC PATCH 0/3] arm64: hibernate: idmap the single page that holds the copy page routines James Morse @ 2020-01-15 14:33 ` James Morse 2020-01-15 14:33 ` [RFC PATCH 2/3] arm64: hibernate: Split create_safe_exec_page() and its mapping code James Morse 2020-01-15 14:33 ` [RFC PATCH 3/3] arm64: hibernate: idmap the single page that holds the copy page routines James Morse 2 siblings, 0 replies; 9+ messages in thread From: James Morse @ 2020-01-15 14:33 UTC (permalink / raw) To: Pavel Tatashin; +Cc: linux-arm-kernel 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 <Lorenzo.Pieralisi@arm.com> CC: Sudeep Holla <sudeep.holla@arm.com> Signed-off-by: James Morse <james.morse@arm.com> --- arch/arm64/include/asm/mmu_context.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index 3827ff4040a3..09ecbfd0ad2e 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -79,16 +79,15 @@ static inline bool __cpu_uses_extended_idmap_level(void) } /* - * Set TCR.T0SZ to its default value (based on VA_BITS) + * Ensure TCR.T0SZ is set to the provided value. */ static inline void __cpu_set_tcr_t0sz(unsigned long t0sz) { - unsigned long tcr; + unsigned long tcr = read_sysreg(tcr_el1); - if (!__cpu_uses_extended_idmap()) + if ((tcr & TCR_T0SZ_MASK) >> TCR_T0SZ_OFFSET == t0sz) return; - tcr = read_sysreg(tcr_el1); tcr &= ~TCR_T0SZ_MASK; tcr |= t0sz << TCR_T0SZ_OFFSET; write_sysreg(tcr, tcr_el1); -- 2.24.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC PATCH 2/3] arm64: hibernate: Split create_safe_exec_page() and its mapping code 2020-01-15 14:33 [RFC PATCH 0/3] arm64: hibernate: idmap the single page that holds the copy page routines James Morse 2020-01-15 14:33 ` [RFC PATCH 1/3] arm64: mm: Always update TCR_EL1 from __cpu_set_tcr_t0sz() James Morse @ 2020-01-15 14:33 ` James Morse 2020-01-15 14:33 ` [RFC PATCH 3/3] arm64: hibernate: idmap the single page that holds the copy page routines James Morse 2 siblings, 0 replies; 9+ messages in thread From: James Morse @ 2020-01-15 14:33 UTC (permalink / raw) To: Pavel Tatashin; +Cc: linux-arm-kernel Kexec wants to share hibernate's page table setup code, but needs its memory-copy buffer idmapped as it also has to turn the MMU off. Split the copy of this buffer from the code that maps it. Signed-off-by: James Morse <james.morse@arm.com> --- arch/arm64/kernel/hibernate.c | 57 +++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index a96b2921d22c..7f8cb7596f9e 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -183,19 +183,9 @@ int arch_hibernation_header_restore(void *addr) EXPORT_SYMBOL(arch_hibernation_header_restore); /* - * Copies length bytes, starting at src_start into an new page, - * perform cache maintentance, then maps it at the specified address low - * address as executable. - * - * This is used by hibernate to copy the code it needs to execute when - * overwriting the kernel text. This function generates a new set of page - * tables, which it loads into ttbr0. - * - * Length is provided as we probably only want 4K of data, even on a 64K - * page system. + * Create a set of page tables that map page to dst_addr. */ -static int create_safe_exec_page(void *src_start, size_t length, - unsigned long dst_addr, +static int create_single_mapping(unsigned long page, unsigned long dst_addr, phys_addr_t *phys_dst_addr, void *(*allocator)(gfp_t mask), gfp_t mask) @@ -206,15 +196,6 @@ static int create_safe_exec_page(void *src_start, size_t length, pud_t *pudp; pmd_t *pmdp; pte_t *ptep; - unsigned long dst = (unsigned long)allocator(mask); - - if (!dst) { - rc = -ENOMEM; - goto out; - } - - memcpy((void *)dst, src_start, length); - __flush_icache_range(dst, dst + length); trans_pgd = allocator(mask); if (!trans_pgd) { @@ -253,7 +234,7 @@ static int create_safe_exec_page(void *src_start, size_t length, } ptep = pte_offset_kernel(pmdp, dst_addr); - set_pte(ptep, pfn_pte(virt_to_pfn(dst), PAGE_KERNEL_EXEC)); + set_pte(ptep, pfn_pte(virt_to_pfn(page), PAGE_KERNEL_EXEC)); /* * Load our new page tables. A strict BBM approach requires that we @@ -272,12 +253,42 @@ static int create_safe_exec_page(void *src_start, size_t length, write_sysreg(phys_to_ttbr(virt_to_phys(pgdp)), ttbr0_el1); isb(); - *phys_dst_addr = virt_to_phys((void *)dst); + *phys_dst_addr = virt_to_phys((void *)page); out: return rc; } +/* + * Copies length bytes, starting at src_start into an new page, + * perform cache maintentance, then maps it at the specified address low + * address as executable. + * + * This is used by hibernate to copy the code it needs to execute when + * overwriting the kernel text. This function generates a new set of page + * tables, which it loads into ttbr0. + * + * Length is provided as we probably only want 4K of data, even on a 64K + * page system. + */ +static int create_safe_exec_page(void *src_start, size_t length, + unsigned long dst_addr, + phys_addr_t *phys_dst_addr, + void *(*allocator)(gfp_t mask), + gfp_t mask) +{ + unsigned long page = (unsigned long)allocator(mask); + + if (!page) + return -ENOMEM; + + memcpy((void *)page, src_start, length); + __flush_icache_range(page, page + length); + + return create_single_mapping(page, dst_addr, phys_dst_addr, + allocator, gfp_t mask) +} + #define dcache_clean_range(start, end) __flush_dcache_area(start, (end - start)) int swsusp_arch_suspend(void) -- 2.24.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [RFC PATCH 3/3] arm64: hibernate: idmap the single page that holds the copy page routines 2020-01-15 14:33 [RFC PATCH 0/3] arm64: hibernate: idmap the single page that holds the copy page routines James Morse 2020-01-15 14:33 ` [RFC PATCH 1/3] arm64: mm: Always update TCR_EL1 from __cpu_set_tcr_t0sz() James Morse 2020-01-15 14:33 ` [RFC PATCH 2/3] arm64: hibernate: Split create_safe_exec_page() and its mapping code James Morse @ 2020-01-15 14:33 ` James Morse 2020-03-20 21:22 ` Pavel Tatashin 2 siblings, 1 reply; 9+ messages in thread From: James Morse @ 2020-01-15 14:33 UTC (permalink / raw) To: Pavel Tatashin; +Cc: linux-arm-kernel 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> --- arch/arm64/kernel/hibernate.c | 109 ++++++++++++++++------------------ 1 file changed, 50 insertions(+), 59 deletions(-) diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 7f8cb7596f9e..b0bceec829c7 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -183,58 +183,57 @@ int arch_hibernation_header_restore(void *addr) EXPORT_SYMBOL(arch_hibernation_header_restore); /* - * Create a set of page tables that map page to dst_addr. + * Create a set of page tables that idmap phys_dst_addr. */ -static int create_single_mapping(unsigned long page, unsigned long dst_addr, - phys_addr_t *phys_dst_addr, +static int create_single_mapping(phys_addr_t phys_dst_addr, void *(*allocator)(gfp_t mask), gfp_t mask) { int rc = 0; - pgd_t *trans_pgd; - pgd_t *pgdp; - pud_t *pudp; - pmd_t *pmdp; - pte_t *ptep; - - trans_pgd = allocator(mask); - if (!trans_pgd) { - rc = -ENOMEM; - goto out; - } + unsigned long level_mask; + int this_level = 3, index; + unsigned long *levels[4] = { }; + unsigned long prev_level_entry; + int bits_mapped = PAGE_SHIFT - 4; + unsigned int level_lsb, level_msb, max_msb; + unsigned long pfn = __phys_to_pfn(phys_dst_addr); + + if (phys_dst_addr & GENMASK(52, 48)) + max_msb = 51; + else + max_msb = 47; - pgdp = pgd_offset_raw(trans_pgd, dst_addr); - if (pgd_none(READ_ONCE(*pgdp))) { - pudp = allocator(mask); - if (!pudp) { - rc = -ENOMEM; - goto out; - } - pgd_populate(&init_mm, pgdp, pudp); - } + /* + * The page we want to idmap may be outside the range covered by + * VA_BITS that can be built using the kernel's p?d_populate() helpers. + * + * As a one off, for a single page, we build these page tables bottom + * up and just assume that will need the maximum T0SZ. + */ + phys_dst_addr &= PAGE_MASK; + prev_level_entry = pte_val(pfn_pte(pfn, PAGE_KERNEL_EXEC)); - pudp = pud_offset(pgdp, dst_addr); - if (pud_none(READ_ONCE(*pudp))) { - pmdp = allocator(mask); - if (!pmdp) { + for (this_level = 3; this_level >= 0; this_level--) { + levels[this_level] = allocator(mask); + if (!levels[this_level]) { rc = -ENOMEM; goto out; } - pud_populate(&init_mm, pudp, pmdp); - } - pmdp = pmd_offset(pudp, dst_addr); - if (pmd_none(READ_ONCE(*pmdp))) { - ptep = allocator(mask); - if (!ptep) { - rc = -ENOMEM; - goto out; - } - pmd_populate_kernel(&init_mm, pmdp, ptep); - } + level_lsb = ARM64_HW_PGTABLE_LEVEL_SHIFT(this_level); + level_msb = min(level_lsb + bits_mapped, max_msb); + level_mask = GENMASK_ULL(level_msb, level_lsb); - ptep = pte_offset_kernel(pmdp, dst_addr); - set_pte(ptep, pfn_pte(virt_to_pfn(page), PAGE_KERNEL_EXEC)); + index = (phys_dst_addr & level_mask) >> level_lsb; + *(levels[this_level] + index) = prev_level_entry; + + pfn = virt_to_pfn(levels[this_level]); + prev_level_entry = pte_val(pfn_pte(pfn, + __pgprot(PMD_TYPE_TABLE))); + + if (level_msb == max_msb) + break; + } /* * Load our new page tables. A strict BBM approach requires that we @@ -245,24 +244,24 @@ static int create_single_mapping(unsigned long page, unsigned long dst_addr, * page, but TLBs may contain stale ASID-tagged entries (e.g. for EFI * runtime services), while for a userspace-driven test_resume cycle it * points to userspace page tables (and we must point it at a zero page - * ourselves). Elsewhere we only (un)install the idmap with preemption - * disabled, so T0SZ should be as required regardless. + * ourselves). + * + * We change T0SZ as part of installing the idmap. This is undone by + * cpu_uninstall_idmap() in __cpu_suspend_exit(). */ cpu_set_reserved_ttbr0(); local_flush_tlb_all(); - write_sysreg(phys_to_ttbr(virt_to_phys(pgdp)), ttbr0_el1); + __cpu_set_tcr_t0sz(TCR_T0SZ(max_msb + 1)); + write_sysreg(phys_to_ttbr(__pfn_to_phys(pfn)), ttbr0_el1); isb(); - *phys_dst_addr = virt_to_phys((void *)page); - out: return rc; } /* * Copies length bytes, starting at src_start into an new page, - * perform cache maintentance, then maps it at the specified address low - * address as executable. + * perform cache maintentance, then idmaps it. * * This is used by hibernate to copy the code it needs to execute when * overwriting the kernel text. This function generates a new set of page @@ -272,7 +271,6 @@ static int create_single_mapping(unsigned long page, unsigned long dst_addr, * page system. */ static int create_safe_exec_page(void *src_start, size_t length, - unsigned long dst_addr, phys_addr_t *phys_dst_addr, void *(*allocator)(gfp_t mask), gfp_t mask) @@ -281,12 +279,12 @@ static int create_safe_exec_page(void *src_start, size_t length, if (!page) return -ENOMEM; + *phys_dst_addr = virt_to_phys((void *)page); memcpy((void *)page, src_start, length); __flush_icache_range(page, page + length); - return create_single_mapping(page, dst_addr, phys_dst_addr, - allocator, gfp_t mask) + return create_single_mapping(*phys_dst_addr, allocator, mask); } #define dcache_clean_range(start, end) __flush_dcache_area(start, (end - start)) @@ -499,7 +497,6 @@ int swsusp_arch_resume(void) void *zero_page; size_t exit_size; pgd_t *tmp_pg_dir; - phys_addr_t phys_hibernate_exit; void __noreturn (*hibernate_exit)(phys_addr_t, phys_addr_t, void *, void *, phys_addr_t, phys_addr_t); @@ -529,19 +526,13 @@ int swsusp_arch_resume(void) goto out; } - /* - * Locate the exit code in the bottom-but-one page, so that *NULL - * still has disastrous affects. - */ - hibernate_exit = (void *)PAGE_SIZE; exit_size = __hibernate_exit_text_end - __hibernate_exit_text_start; /* * Copy swsusp_arch_suspend_exit() to a safe page. This will generate * a new set of ttbr0 page tables and load them. */ rc = create_safe_exec_page(__hibernate_exit_text_start, exit_size, - (unsigned long)hibernate_exit, - &phys_hibernate_exit, + (phys_addr_t *)&hibernate_exit, (void *)get_safe_page, GFP_ATOMIC); if (rc) { pr_err("Failed to create safe executable page for hibernate_exit code.\n"); @@ -561,7 +552,7 @@ int swsusp_arch_resume(void) * We can skip this step if we booted at EL1, or are running with VHE. */ if (el2_reset_needed()) { - phys_addr_t el2_vectors = phys_hibernate_exit; /* base */ + phys_addr_t el2_vectors = (phys_addr_t)hibernate_exit;/* base */ el2_vectors += hibernate_el2_vectors - __hibernate_exit_text_start; /* offset */ -- 2.24.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 3/3] arm64: hibernate: idmap the single page that holds the copy page routines 2020-01-15 14:33 ` [RFC PATCH 3/3] arm64: hibernate: idmap the single page that holds the copy page routines James Morse @ 2020-03-20 21:22 ` Pavel Tatashin 2020-03-25 9:58 ` James Morse 0 siblings, 1 reply; 9+ messages in thread From: Pavel Tatashin @ 2020-03-20 21:22 UTC (permalink / raw) To: James Morse; +Cc: Linux ARM Hi James, Sorry, for a slow response. Soon, I will send out updated MMU enabled kexec series which will have this work included. I appreciate your help with this. > 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. Makes sense. > Convert create_single_mapping() to take a single PA, and idmap it. I like the idea of using idmap in both places! > 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. I do not think this will work for kexec case. In hibernate we map only one page, so we can allocate every level from bottom to top, but in kexec we map many pages. So, upper levels might already exist. I think we will need to modify the loop to still go from top to bottom. Otherwise, this work makes sense. I will integrate it into my series. Thank you, Pasha _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 3/3] arm64: hibernate: idmap the single page that holds the copy page routines 2020-03-20 21:22 ` Pavel Tatashin @ 2020-03-25 9:58 ` James Morse 2020-03-25 13:29 ` Pavel Tatashin 0 siblings, 1 reply; 9+ messages in thread From: James Morse @ 2020-03-25 9:58 UTC (permalink / raw) To: Pavel Tatashin; +Cc: Linux ARM Hi Pavel, On 3/20/20 9:22 PM, Pavel Tatashin wrote: > Soon, I will send out updated MMU enabled kexec series which will have > this work included. I appreciate your help with this. > >> 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. > > Makes sense. >> Convert create_single_mapping() to take a single PA, and idmap it. > > I like the idea of using idmap in both places! This is the only way this should work. Both hibernate and kexec replace all of memory, with the MMU on, while using a temporary set of page tables. As much of the code that does this should be shared. Hibernate already does all of this, so kexec should re-use that code. >> 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. > > I do not think this will work for kexec case. In hibernate we map only > one page, so we can allocate every level from bottom to top, but in > kexec we map many pages. So, upper levels might already exist. I think > we will need to modify the loop to still go from top to bottom. No. We should not have a second set of helpers for building page tables for kexec, its an unnecessary maintenance burden. You keep coming back to this because you are trying to idmap all memory on arm64. You do not need to do this. You only need one page idmaped so you can switch TTBR1_EL1, and turn the MMU off. You can do the copy of memory using a copy of the linear map in TTBR1_EL1. For an example: hibernate does exactly this. This saves all the hassle of nomap, reserved-firmware pages and the risk of introducing mismatched attributes. (which would lead to mysterious coherency issues for the next kernel) Your answer is going to be that kexec's data structures are physically addressed. The linear map, is linear: You can convert the kexec:physical-address to a KASLR'd linear-map virtual address, with addition. (beware, the kaslr offset is _signed_, it can be negative!) The code in this RFC was particularly tricky to test as its behaviour depends on which bits of a pointer are set. This code is complicated, and impossible to debug if it goes wrong. (photograph of a screen with the word 'Bye' on it anyone?). Worse: it must not introduce coherency issues into the next kernel. It must be as simple as possible. What you are proposing is not. Thanks, James _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 3/3] arm64: hibernate: idmap the single page that holds the copy page routines 2020-03-25 9:58 ` James Morse @ 2020-03-25 13:29 ` Pavel Tatashin 2020-03-25 13:41 ` Pavel Tatashin 2020-03-25 17:08 ` James Morse 0 siblings, 2 replies; 9+ messages in thread From: Pavel Tatashin @ 2020-03-25 13:29 UTC (permalink / raw) To: James Morse; +Cc: Linux ARM Hi James, > You keep coming back to this because you are trying to idmap all memory > on arm64. You do not need to do this. No, this is not what I am trying to do. That approach was done in my first RFC, but I have since abandoned it, and I now have proper liner copy configured in TTBR1: See: https://lore.kernel.org/lkml/20191204155938.2279686-24-pasha.tatashin@soleen.com +/* + * Map source segments starting from KEXEC_SRC_START, and map destination + * segments starting from KEXEC_DST_START, and return size of copy in + * *copy_len argument. + * Relocation function essentially needs to do: + * memcpy(KEXEC_DST_START, KEXEC_SRC_START, copy_len); + */ Sorry, I made a misleading comment that kexec needs to idmap many pages, in fact it actually needs to idmap only two pages with the current approach: 1. relocation function 2. relocation function argument I could fit both of them into a single pages (the relocation function body is tiny, and argument only contains 9 fields, so 72 bytes), it will be a little ugly though to have them setup like that, so if you have a better suggestion please let me know. > You only need one page idmaped so you can switch TTBR1_EL1, and turn the > MMU off. > > > You can do the copy of memory using a copy of the linear map in > TTBR1_EL1. For an example: hibernate does exactly this. Yes, this is exactly what I am currently doing. > The code in this RFC was particularly tricky to test as its behaviour > depends on which bits of a pointer are set. > > This code is complicated, and impossible to debug if it goes wrong. > (photograph of a screen with the word 'Bye' on it anyone?). Worse: it > must not introduce coherency issues into the next kernel. > > It must be as simple as possible. What you are proposing is not. > I agree. So, let me modify kexec to idmap exactly one page (I will stuff argument and body into a single page), and re-use it with hibernate as you proposed. Thank you, Pasha _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 3/3] arm64: hibernate: idmap the single page that holds the copy page routines 2020-03-25 13:29 ` Pavel Tatashin @ 2020-03-25 13:41 ` Pavel Tatashin 2020-03-25 17:08 ` James Morse 1 sibling, 0 replies; 9+ messages in thread From: Pavel Tatashin @ 2020-03-25 13:41 UTC (permalink / raw) To: James Morse; +Cc: Linux ARM On Wed, Mar 25, 2020 at 9:29 AM Pavel Tatashin <pasha.tatashin@soleen.com> wrote: > > Hi James, > > > You keep coming back to this because you are trying to idmap all memory > > on arm64. You do not need to do this. > > No, this is not what I am trying to do. That approach was done in my > first RFC, but I have since abandoned it, and I now have proper liner > copy configured in TTBR1: > See: https://lore.kernel.org/lkml/20191204155938.2279686-24-pasha.tatashin@soleen.com > +/* > + * Map source segments starting from KEXEC_SRC_START, and map destination > + * segments starting from KEXEC_DST_START, and return size of copy in > + * *copy_len argument. > + * Relocation function essentially needs to do: > + * memcpy(KEXEC_DST_START, KEXEC_SRC_START, copy_len); > + */ > > Sorry, I made a misleading comment that kexec needs to idmap many > pages, in fact it actually needs to idmap only two pages with the > current approach: > > 1. relocation function > 2. relocation function argument > > I could fit both of them into a single pages (the relocation function > body is tiny, and argument only contains 9 fields, so 72 bytes), it > will be a little ugly though to have them setup like that, so if you > have a better suggestion please let me know. Nevermind. I figured we do not really need to idmap argument. In arm64_relocate_new_kernel() while MMU is off we have plenty of registers. I will simply load all argument arguments into free registers before turning MMU on. > > > You only need one page idmaped so you can switch TTBR1_EL1, and turn the > > MMU off. > > > > > > You can do the copy of memory using a copy of the linear map in > > TTBR1_EL1. For an example: hibernate does exactly this. > > Yes, this is exactly what I am currently doing. > > > The code in this RFC was particularly tricky to test as its behaviour > > depends on which bits of a pointer are set. > > > > This code is complicated, and impossible to debug if it goes wrong. > > (photograph of a screen with the word 'Bye' on it anyone?). Worse: it > > must not introduce coherency issues into the next kernel. > > > > It must be as simple as possible. What you are proposing is not. > > > > I agree. So, let me modify kexec to idmap exactly one page (I will > stuff argument and body into a single page), and re-use it with > hibernate as you proposed. > > Thank you, > Pasha _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [RFC PATCH 3/3] arm64: hibernate: idmap the single page that holds the copy page routines 2020-03-25 13:29 ` Pavel Tatashin 2020-03-25 13:41 ` Pavel Tatashin @ 2020-03-25 17:08 ` James Morse 1 sibling, 0 replies; 9+ messages in thread From: James Morse @ 2020-03-25 17:08 UTC (permalink / raw) To: Pavel Tatashin; +Cc: Linux ARM Hi Pavel, On 3/25/20 1:29 PM, Pavel Tatashin wrote: >> You keep coming back to this because you are trying to idmap all memory >> on arm64. You do not need to do this. > > No, this is not what I am trying to do. That approach was done in my > first RFC, but I have since abandoned it, Ah, okay. These all merge into one! >> You only need one page idmaped so you can switch TTBR1_EL1, and turn the >> MMU off. >> >> >> You can do the copy of memory using a copy of the linear map in >> TTBR1_EL1. For an example: hibernate does exactly this. > > Yes, this is exactly what I am currently doing. Great! Thanks, James _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2020-03-25 17:08 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-01-15 14:33 [RFC PATCH 0/3] arm64: hibernate: idmap the single page that holds the copy page routines James Morse 2020-01-15 14:33 ` [RFC PATCH 1/3] arm64: mm: Always update TCR_EL1 from __cpu_set_tcr_t0sz() James Morse 2020-01-15 14:33 ` [RFC PATCH 2/3] arm64: hibernate: Split create_safe_exec_page() and its mapping code James Morse 2020-01-15 14:33 ` [RFC PATCH 3/3] arm64: hibernate: idmap the single page that holds the copy page routines James Morse 2020-03-20 21:22 ` Pavel Tatashin 2020-03-25 9:58 ` James Morse 2020-03-25 13:29 ` Pavel Tatashin 2020-03-25 13:41 ` Pavel Tatashin 2020-03-25 17:08 ` James Morse
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).