Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: use virt_to_idmap() for soft_restart()

Code run via soft_restart() is run with the MMU disabled, so we need to
pass the identity map physical address rather than the address obtained
from virt_to_phys(). Therefore, replace virt_to_phys() with
virt_to_idmap() for all callers of soft_restart().

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

+8 -12
+2 -2
arch/arm/kernel/hibernate.c
··· 62 62 63 63 ret = swsusp_save(); 64 64 if (ret == 0) 65 - _soft_restart(virt_to_phys(cpu_resume), false); 65 + _soft_restart(virt_to_idmap(cpu_resume), false); 66 66 return ret; 67 67 } 68 68 ··· 87 87 for (pbe = restore_pblist; pbe; pbe = pbe->next) 88 88 copy_page(pbe->orig_address, pbe->address); 89 89 90 - _soft_restart(virt_to_phys(cpu_resume), false); 90 + _soft_restart(virt_to_idmap(cpu_resume), false); 91 91 } 92 92 93 93 static u64 resume_stack[PAGE_SIZE/2/sizeof(u64)] __nosavedata;
+6 -10
arch/arm/kernel/machine_kexec.c
··· 143 143 144 144 void machine_kexec(struct kimage *image) 145 145 { 146 - unsigned long page_list; 147 - unsigned long reboot_code_buffer_phys; 148 - unsigned long reboot_entry = (unsigned long)relocate_new_kernel; 149 - unsigned long reboot_entry_phys; 146 + unsigned long page_list, reboot_entry_phys; 147 + void (*reboot_entry)(void); 150 148 void *reboot_code_buffer; 151 149 152 150 /* ··· 157 159 158 160 page_list = image->head & PAGE_MASK; 159 161 160 - /* we need both effective and real address here */ 161 - reboot_code_buffer_phys = 162 - page_to_pfn(image->control_code_page) << PAGE_SHIFT; 163 162 reboot_code_buffer = page_address(image->control_code_page); 164 163 165 164 /* Prepare parameters for reboot_code_buffer*/ ··· 169 174 170 175 /* copy our kernel relocation code to the control code page */ 171 176 reboot_entry = fncpy(reboot_code_buffer, 172 - reboot_entry, 177 + &relocate_new_kernel, 173 178 relocate_new_kernel_size); 174 - reboot_entry_phys = (unsigned long)reboot_entry + 175 - (reboot_code_buffer_phys - (unsigned long)reboot_code_buffer); 179 + 180 + /* get the identity mapping physical address for the reboot code */ 181 + reboot_entry_phys = virt_to_idmap(reboot_entry); 176 182 177 183 pr_info("Bye!\n"); 178 184