Message ID | 20240814124613.2632226-4-kirill.shutemov@linux.intel.com |
---|---|
State | Superseded |
Headers | show |
Series | x86: Reduce code duplication on page table initialization | expand |
Cc Eric and kexec mailing list. On 08/14/24 at 03:46pm, Kirill A. Shutemov wrote: > The init_transition_pgtable() function sets up transitional page tables. > It ensures that the relocate_kernel() function is present in the > identity mapping at the same location as in the kernel page tables. > relocate_kernel() switches to the identity mapping, and the function > must be present at the same location in the virtual address space before > and after switching page tables. > > init_transition_pgtable() maps a copy of relocate_kernel() in > image->control_code_page at the relocate_kernel() virtual address, but > the original physical address of relocate_kernel() would also work. > > It is safe to use original relocate_kernel() physical address cannot be > overwritten until swap_pages() is called, and the relocate_kernel() > virtual address will not be used by then. I haven't read these codes for long time, wondering if we still need copy relocate_kernel() to image->control_code_page + PAGE_SIZE as you said. > > Map the original relocate_kernel() at the relocate_kernel() virtual > address in the identity mapping. It is preparation to replace the > init_transition_pgtable() implementation with a call to > kernel_ident_mapping_init(). > > Note that while relocate_kernel() switches to the identity mapping, it > does not flush global TLB entries (CR4.PGE is not cleared). This means > that in most cases, the kernel still runs relocate_kernel() from the > original physical address before the change. > > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> > --- > arch/x86/kernel/machine_kexec_64.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c > index 9c9ac606893e..645690e81c2d 100644 > --- a/arch/x86/kernel/machine_kexec_64.c > +++ b/arch/x86/kernel/machine_kexec_64.c > @@ -157,7 +157,7 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) > pte_t *pte; > > vaddr = (unsigned long)relocate_kernel; > - paddr = __pa(page_address(image->control_code_page)+PAGE_SIZE); > + paddr = __pa(relocate_kernel); > pgd += pgd_index(vaddr); > if (!pgd_present(*pgd)) { > p4d = (p4d_t *)get_zeroed_page(GFP_KERNEL); > -- > 2.43.0 >
On Thu, Aug 15, 2024 at 02:15:40PM +0800, Baoquan He wrote: > Cc Eric and kexec mailing list. > > On 08/14/24 at 03:46pm, Kirill A. Shutemov wrote: > > The init_transition_pgtable() function sets up transitional page tables. > > It ensures that the relocate_kernel() function is present in the > > identity mapping at the same location as in the kernel page tables. > > relocate_kernel() switches to the identity mapping, and the function > > must be present at the same location in the virtual address space before > > and after switching page tables. > > > > init_transition_pgtable() maps a copy of relocate_kernel() in > > image->control_code_page at the relocate_kernel() virtual address, but > > the original physical address of relocate_kernel() would also work. > > > > It is safe to use original relocate_kernel() physical address cannot be > > overwritten until swap_pages() is called, and the relocate_kernel() > > virtual address will not be used by then. > > I haven't read these codes for long time, wondering if we still need > copy relocate_kernel() to image->control_code_page + PAGE_SIZE as you > said. I think we can get away with only coping starting with identity_mapped(). But given that KEXEC_CONTROL_CODE_MAX_SIZE is 2K I don't see a reason to change anything here.
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 9c9ac606893e..645690e81c2d 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -157,7 +157,7 @@ static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) pte_t *pte; vaddr = (unsigned long)relocate_kernel; - paddr = __pa(page_address(image->control_code_page)+PAGE_SIZE); + paddr = __pa(relocate_kernel); pgd += pgd_index(vaddr); if (!pgd_present(*pgd)) { p4d = (p4d_t *)get_zeroed_page(GFP_KERNEL);
The init_transition_pgtable() function sets up transitional page tables. It ensures that the relocate_kernel() function is present in the identity mapping at the same location as in the kernel page tables. relocate_kernel() switches to the identity mapping, and the function must be present at the same location in the virtual address space before and after switching page tables. init_transition_pgtable() maps a copy of relocate_kernel() in image->control_code_page at the relocate_kernel() virtual address, but the original physical address of relocate_kernel() would also work. It is safe to use original relocate_kernel() physical address cannot be overwritten until swap_pages() is called, and the relocate_kernel() virtual address will not be used by then. Map the original relocate_kernel() at the relocate_kernel() virtual address in the identity mapping. It is preparation to replace the init_transition_pgtable() implementation with a call to kernel_ident_mapping_init(). Note that while relocate_kernel() switches to the identity mapping, it does not flush global TLB entries (CR4.PGE is not cleared). This means that in most cases, the kernel still runs relocate_kernel() from the original physical address before the change. Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> --- arch/x86/kernel/machine_kexec_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)