On 07/06/17 at 09:28pm, Baoquan He wrote: > > > Do you mean the handling in boot/compressed/head_64.S? Whatever it does, > > > it's only for physical address. The virtual address mapping is not > > > touched. Here virt_addr respresents the offset between > > > 0xffffffff80000000, 0xffffffffc0000000. And if skip the relocation > > > handling, we can see that the '_text' will be mapped to > > > 0xffffffff81000000 forever, no matter where physical address of '_text' > > > is. So here LOAD_PHYSICAL_ADDR is default value of 'virt_addr'. > > > > So, this isn't always true. The output address is the address assigned > > by head_*.S for the extraction destination. We can't just change that, > > since it's based on where to perform the extraction, etc. All the > > logic in there is designed to make sure we're actually >= > > LOAD_PHYSICAL_ADDR: > > > > cmpl $LOAD_PHYSICAL_ADDR, %ebx > > jge 1f > > #endif > > movl $LOAD_PHYSICAL_ADDR, %ebx > > 1: > > Yes, here it's trying to do an adjustment. To align the original loading > address if it's not aligned to CONFIG_PHYSICAL_ALIGN, and to make it be > LOAD_PHYSICAL_ADDR if it's smaller than LOAD_PHYSICAL_ADDR. Other than > those, nothing else be done. So let me conclude the possible original > 'output' value: > 1) default case > It's LOAD_PHYSICAL_ADDR Which is the default loading address. > 2) kexec/kdump > The output will be at the top of the available physical ram. > 3) Modified bootloader > Which could put kernel anywhere by modifying code of bootloader. This > is the case that we need do above alignment and adjustment to avoid > unpleasant kernel error. > > Except of above 3 cases, physical address of kernel could be changed by > physical address randomization. > 4) physical address randomization > > However, for virtual address, there are only two chances to decide: > 1) arch/x86/kernel/vmlinux.lds.S > we just map .text at __START_KERNEL > #define __PHYSICAL_START ALIGN(CONFIG_PHYSICAL_START, \ > > CONFIG_PHYSICAL_ALIGN) > > #define __START_KERNEL (__START_KERNEL_map + __PHYSICAL_START) > 2) handle_relocations :: boot/compressed/misc.c > In handle_relocations(), we DO pass in the physical 'output', but that > is used to calculate 'map' which is used to position those memory > unit where the referenced address need be relocated. > > So later, in arch/x86/kernel/head_64.S, we will store the delta which is > between 16M and the actual kernel loading address into phys_base. So as
Here I was wrong about phys_base. It has been changed in the latest code in Linus's tree. Please check arch/x86/kernel/head64.c: void __head __startup_64(unsigned long physaddr) { ... load_delta = physaddr - (unsigned long)(_text - __START_KERNEL_map); ... /* Fixup phys_base */ p = fixup_pointer(&phys_base, physaddr); *p += load_delta; } Here physaddr should be 'output' which is the place kernel decompressed at. > long as we can translate physical address and virtual address of kernel > by below formula, everything is going very well. > > y = x - __START_KERNEL_map + phys_base. > > We really don't need to tie physical address and virtual address of > kernel together in any cases. They can be randomized or not randomized > completely separately. As long as we keep above translation formula > working well, everything need not be worried.