hv: fixup relocation delta for symbols belong to entry section
This is to enable relocation for code32. - RIP relative addressing is available in x86-64 only so we manually add relocation delta to the target symbols to fixup code32. - both code32 and code64 need to load GDT hence both need to fixup GDT pointer. This patch declares separate GDT pointer cpu_primary64_gdt_ptr for code64 to avoid double fixup. - manually fixup cpu_primary64_gdt_ptr in code64, but not rely on relocate() to do that. Otherwise it's very confusing that symbols from same file could be fixed up externally by relocate() or self-relocated. - to make it clear, define a new symbol ld_entry_end representing the end of the boot code that needs manually fixup, and use this symbol in relocate() to filter out all symbols belong to the entry sections. Tracked-On: #4441 Reviewed-by: Fengwei Yin <fengwei.yin@intel.com> Signed-off-by: Zide Chen <zide.chen@intel.com>
This commit is contained in:
parent
2aa8c9e5d4
commit
49ffe168af
|
@ -122,9 +122,18 @@ mb2_header_end:
|
|||
|
||||
.global cpu_primary_start_32
|
||||
cpu_primary_start_32:
|
||||
|
||||
/*
|
||||
* Calculate the relocation delta between where we were compiled to run
|
||||
* at and where we were actually loaded at.
|
||||
*/
|
||||
call 0f
|
||||
0: pop %esi
|
||||
sub $0b, %esi
|
||||
|
||||
/* save the MULTBOOT magic number & MBI */
|
||||
movl %eax, (boot_regs)
|
||||
movl %ebx, (boot_regs+4)
|
||||
movl %eax, boot_regs(%esi)
|
||||
movl %ebx, (boot_regs+4)(%esi)
|
||||
|
||||
/* Disable interrupts */
|
||||
cli
|
||||
|
@ -156,8 +165,16 @@ cpu_primary_start_32:
|
|||
movl $0x00000668, %eax
|
||||
mov %eax, %cr4
|
||||
|
||||
/* fixup page table pointers with relocation delta */
|
||||
addl %esi, cpu_primary32_pdpt_addr(%esi)
|
||||
addl %esi, (cpu_primary32_pdpt_addr+8)(%esi)
|
||||
addl %esi, (cpu_primary32_pdpt_addr+16)(%esi)
|
||||
addl %esi, (cpu_primary32_pdpt_addr+24)(%esi)
|
||||
|
||||
/* Set CR3 to PML4 table address */
|
||||
movl $cpu_boot32_page_tables_start, %edi
|
||||
addl %esi, %edi
|
||||
addl %esi, (%edi)
|
||||
mov %edi, %cr3
|
||||
|
||||
/* Set LME bit in EFER */
|
||||
|
@ -178,11 +195,20 @@ cpu_primary_start_32:
|
|||
|
||||
/* Load temportary GDT pointer value */
|
||||
mov $cpu_primary32_gdt_ptr, %ebx
|
||||
addl %esi, %ebx
|
||||
addl %esi, 2(%ebx)
|
||||
lgdt (%ebx)
|
||||
|
||||
/* Perform a long jump based to start executing in 64-bit mode */
|
||||
movl $jmpbuf_32, %eax
|
||||
addl %esi, %eax
|
||||
addl %esi, (%eax)
|
||||
ljmp *(%eax)
|
||||
|
||||
jmpbuf_32:
|
||||
.long primary_start_long_mode
|
||||
/* 0x0008 = HOST_GDT_RING0_CODE_SEL */
|
||||
ljmp $0x0008, $primary_start_long_mode
|
||||
.word 0x0008
|
||||
|
||||
.code64
|
||||
.org 0x200
|
||||
|
@ -212,17 +238,22 @@ primary_start_long_mode:
|
|||
*/
|
||||
call relocate
|
||||
|
||||
call 0f
|
||||
0: pop %rsi
|
||||
sub $0b, %rsi /* relocation delta */
|
||||
|
||||
/* Load temportary GDT pointer value */
|
||||
lea cpu_primary32_gdt_ptr(%rip), %rbx
|
||||
lea cpu_primary64_gdt_ptr(%rip), %rbx
|
||||
addq %rsi, 2(%rbx)
|
||||
lgdt (%ebx)
|
||||
|
||||
/* Set the correct long jump address */
|
||||
lea jmpbuf(%rip), %rax
|
||||
lea jmpbuf_64(%rip), %rax
|
||||
lea after(%rip), %rbx
|
||||
mov %rbx, (%rax)
|
||||
rex.w ljmp *(%rax)
|
||||
.data
|
||||
jmpbuf: .quad 0
|
||||
jmpbuf_64: .quad 0
|
||||
/* 0x0008 = HOST_GDT_RING0_CODE_SEL */
|
||||
.word 0x0008
|
||||
.text
|
||||
|
@ -261,6 +292,10 @@ cpu_primary32_gdt_ptr:
|
|||
.short (cpu_primary32_gdt_end - cpu_primary32_gdt) - 1
|
||||
.quad cpu_primary32_gdt
|
||||
|
||||
cpu_primary64_gdt_ptr:
|
||||
.short (cpu_primary32_gdt_end - cpu_primary32_gdt) - 1
|
||||
.quad cpu_primary32_gdt
|
||||
|
||||
/* PML4, PDPT, and PD tables initialized to map first 4 GBytes of memory */
|
||||
/*0x1000 = PAGE_SIZE*/
|
||||
.align 0x1000
|
||||
|
|
|
@ -13,7 +13,4 @@ extern uint64_t get_hv_image_base(void);
|
|||
/* external symbols that are helpful for relocation */
|
||||
extern uint8_t _DYNAMIC[1];
|
||||
|
||||
extern uint8_t cpu_primary_start_32;
|
||||
extern uint8_t cpu_primary_start_64;
|
||||
|
||||
#endif /* RELOCATE_H */
|
||||
|
|
|
@ -64,7 +64,7 @@ void relocate(void)
|
|||
uint64_t rela_size = 0;
|
||||
uint64_t delta, entry_size = 0;
|
||||
uint64_t trampoline_end;
|
||||
uint64_t primary_32_start, primary_32_end;
|
||||
uint64_t primary_entry_end;
|
||||
uint64_t *addr;
|
||||
|
||||
/* get the delta that needs to be patched */
|
||||
|
@ -94,8 +94,7 @@ void relocate(void)
|
|||
* absolute addresses
|
||||
*/
|
||||
trampoline_end = (uint64_t)(&ld_trampoline_end) - delta;
|
||||
primary_32_start = (uint64_t)(&cpu_primary_start_32) - delta;
|
||||
primary_32_end = (uint64_t)(&cpu_primary_start_64) - delta;
|
||||
primary_entry_end = (uint64_t)(&ld_entry_end) - delta;
|
||||
|
||||
rela_end = rela_start + rela_size;
|
||||
while (rela_start < rela_end) {
|
||||
|
@ -104,22 +103,17 @@ void relocate(void)
|
|||
addr = (uint64_t *)(delta + entry->r_offset);
|
||||
|
||||
/*
|
||||
* we won't fixup any trampoline.S and cpu_primary.S here
|
||||
* we won't fixup any symbols from trampoline.S or cpu_primary.S
|
||||
* for a number of reasons:
|
||||
*
|
||||
* - trampoline code itself takes another relocation,
|
||||
* so any entries for trampoline symbols can't be fixed up
|
||||
* through .rela sections
|
||||
* - In cpu_primary.S, the 32 bits code doesn't need relocation
|
||||
* - Linker option "-z noreloc-overflow" could force R_X86_32
|
||||
* to R_X86_64 in the relocation sections, which could make
|
||||
* the fixed up code dirty. Even if relocation for 32 bits
|
||||
* is needed in the future, it's recommended to do it
|
||||
* explicitly in the assembly code to avoid confusion.
|
||||
* the fixed up code dirty.
|
||||
*/
|
||||
if ((entry->r_offset > trampoline_end) &&
|
||||
((entry->r_offset < primary_32_start) ||
|
||||
(entry->r_offset > primary_32_end))) {
|
||||
if ((entry->r_offset > trampoline_end) && (entry->r_offset > primary_entry_end)) {
|
||||
*addr += delta;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ SECTIONS
|
|||
.entry :
|
||||
{
|
||||
KEEP(*(entry)) ;
|
||||
ld_entry_end = . ;
|
||||
|
||||
} > ram
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
extern uint8_t ld_text_end;
|
||||
extern uint8_t ld_bss_start;
|
||||
extern uint8_t ld_bss_end;
|
||||
extern uint8_t ld_entry_end;
|
||||
extern const uint8_t ld_trampoline_load;
|
||||
extern uint8_t ld_trampoline_start;
|
||||
extern uint8_t ld_trampoline_end;
|
||||
|
|
Loading…
Reference in New Issue