mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-25 06:51:49 +00:00
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
|
.global cpu_primary_start_32
|
||||||
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 */
|
/* save the MULTBOOT magic number & MBI */
|
||||||
movl %eax, (boot_regs)
|
movl %eax, boot_regs(%esi)
|
||||||
movl %ebx, (boot_regs+4)
|
movl %ebx, (boot_regs+4)(%esi)
|
||||||
|
|
||||||
/* Disable interrupts */
|
/* Disable interrupts */
|
||||||
cli
|
cli
|
||||||
@ -156,8 +165,16 @@ cpu_primary_start_32:
|
|||||||
movl $0x00000668, %eax
|
movl $0x00000668, %eax
|
||||||
mov %eax, %cr4
|
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 */
|
/* Set CR3 to PML4 table address */
|
||||||
movl $cpu_boot32_page_tables_start, %edi
|
movl $cpu_boot32_page_tables_start, %edi
|
||||||
|
addl %esi, %edi
|
||||||
|
addl %esi, (%edi)
|
||||||
mov %edi, %cr3
|
mov %edi, %cr3
|
||||||
|
|
||||||
/* Set LME bit in EFER */
|
/* Set LME bit in EFER */
|
||||||
@ -178,11 +195,20 @@ cpu_primary_start_32:
|
|||||||
|
|
||||||
/* Load temportary GDT pointer value */
|
/* Load temportary GDT pointer value */
|
||||||
mov $cpu_primary32_gdt_ptr, %ebx
|
mov $cpu_primary32_gdt_ptr, %ebx
|
||||||
|
addl %esi, %ebx
|
||||||
|
addl %esi, 2(%ebx)
|
||||||
lgdt (%ebx)
|
lgdt (%ebx)
|
||||||
|
|
||||||
/* Perform a long jump based to start executing in 64-bit mode */
|
/* 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 */
|
/* 0x0008 = HOST_GDT_RING0_CODE_SEL */
|
||||||
ljmp $0x0008, $primary_start_long_mode
|
.word 0x0008
|
||||||
|
|
||||||
.code64
|
.code64
|
||||||
.org 0x200
|
.org 0x200
|
||||||
@ -212,17 +238,22 @@ primary_start_long_mode:
|
|||||||
*/
|
*/
|
||||||
call relocate
|
call relocate
|
||||||
|
|
||||||
|
call 0f
|
||||||
|
0: pop %rsi
|
||||||
|
sub $0b, %rsi /* relocation delta */
|
||||||
|
|
||||||
/* Load temportary GDT pointer value */
|
/* 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)
|
lgdt (%ebx)
|
||||||
|
|
||||||
/* Set the correct long jump address */
|
/* Set the correct long jump address */
|
||||||
lea jmpbuf(%rip), %rax
|
lea jmpbuf_64(%rip), %rax
|
||||||
lea after(%rip), %rbx
|
lea after(%rip), %rbx
|
||||||
mov %rbx, (%rax)
|
mov %rbx, (%rax)
|
||||||
rex.w ljmp *(%rax)
|
rex.w ljmp *(%rax)
|
||||||
.data
|
.data
|
||||||
jmpbuf: .quad 0
|
jmpbuf_64: .quad 0
|
||||||
/* 0x0008 = HOST_GDT_RING0_CODE_SEL */
|
/* 0x0008 = HOST_GDT_RING0_CODE_SEL */
|
||||||
.word 0x0008
|
.word 0x0008
|
||||||
.text
|
.text
|
||||||
@ -261,6 +292,10 @@ cpu_primary32_gdt_ptr:
|
|||||||
.short (cpu_primary32_gdt_end - cpu_primary32_gdt) - 1
|
.short (cpu_primary32_gdt_end - cpu_primary32_gdt) - 1
|
||||||
.quad cpu_primary32_gdt
|
.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 */
|
/* PML4, PDPT, and PD tables initialized to map first 4 GBytes of memory */
|
||||||
/*0x1000 = PAGE_SIZE*/
|
/*0x1000 = PAGE_SIZE*/
|
||||||
.align 0x1000
|
.align 0x1000
|
||||||
|
@ -13,7 +13,4 @@ extern uint64_t get_hv_image_base(void);
|
|||||||
/* external symbols that are helpful for relocation */
|
/* external symbols that are helpful for relocation */
|
||||||
extern uint8_t _DYNAMIC[1];
|
extern uint8_t _DYNAMIC[1];
|
||||||
|
|
||||||
extern uint8_t cpu_primary_start_32;
|
|
||||||
extern uint8_t cpu_primary_start_64;
|
|
||||||
|
|
||||||
#endif /* RELOCATE_H */
|
#endif /* RELOCATE_H */
|
||||||
|
@ -64,7 +64,7 @@ void relocate(void)
|
|||||||
uint64_t rela_size = 0;
|
uint64_t rela_size = 0;
|
||||||
uint64_t delta, entry_size = 0;
|
uint64_t delta, entry_size = 0;
|
||||||
uint64_t trampoline_end;
|
uint64_t trampoline_end;
|
||||||
uint64_t primary_32_start, primary_32_end;
|
uint64_t primary_entry_end;
|
||||||
uint64_t *addr;
|
uint64_t *addr;
|
||||||
|
|
||||||
/* get the delta that needs to be patched */
|
/* get the delta that needs to be patched */
|
||||||
@ -94,8 +94,7 @@ void relocate(void)
|
|||||||
* absolute addresses
|
* absolute addresses
|
||||||
*/
|
*/
|
||||||
trampoline_end = (uint64_t)(&ld_trampoline_end) - delta;
|
trampoline_end = (uint64_t)(&ld_trampoline_end) - delta;
|
||||||
primary_32_start = (uint64_t)(&cpu_primary_start_32) - delta;
|
primary_entry_end = (uint64_t)(&ld_entry_end) - delta;
|
||||||
primary_32_end = (uint64_t)(&cpu_primary_start_64) - delta;
|
|
||||||
|
|
||||||
rela_end = rela_start + rela_size;
|
rela_end = rela_start + rela_size;
|
||||||
while (rela_start < rela_end) {
|
while (rela_start < rela_end) {
|
||||||
@ -104,22 +103,17 @@ void relocate(void)
|
|||||||
addr = (uint64_t *)(delta + entry->r_offset);
|
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:
|
* for a number of reasons:
|
||||||
*
|
*
|
||||||
* - trampoline code itself takes another relocation,
|
* - trampoline code itself takes another relocation,
|
||||||
* so any entries for trampoline symbols can't be fixed up
|
* so any entries for trampoline symbols can't be fixed up
|
||||||
* through .rela sections
|
* 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
|
* - Linker option "-z noreloc-overflow" could force R_X86_32
|
||||||
* to R_X86_64 in the relocation sections, which could make
|
* to R_X86_64 in the relocation sections, which could make
|
||||||
* the fixed up code dirty. Even if relocation for 32 bits
|
* the fixed up code dirty.
|
||||||
* is needed in the future, it's recommended to do it
|
|
||||||
* explicitly in the assembly code to avoid confusion.
|
|
||||||
*/
|
*/
|
||||||
if ((entry->r_offset > trampoline_end) &&
|
if ((entry->r_offset > trampoline_end) && (entry->r_offset > primary_entry_end)) {
|
||||||
((entry->r_offset < primary_32_start) ||
|
|
||||||
(entry->r_offset > primary_32_end))) {
|
|
||||||
*addr += delta;
|
*addr += delta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ SECTIONS
|
|||||||
.entry :
|
.entry :
|
||||||
{
|
{
|
||||||
KEEP(*(entry)) ;
|
KEEP(*(entry)) ;
|
||||||
|
ld_entry_end = . ;
|
||||||
|
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
extern uint8_t ld_text_end;
|
extern uint8_t ld_text_end;
|
||||||
extern uint8_t ld_bss_start;
|
extern uint8_t ld_bss_start;
|
||||||
extern uint8_t ld_bss_end;
|
extern uint8_t ld_bss_end;
|
||||||
|
extern uint8_t ld_entry_end;
|
||||||
extern const uint8_t ld_trampoline_load;
|
extern const uint8_t ld_trampoline_load;
|
||||||
extern uint8_t ld_trampoline_start;
|
extern uint8_t ld_trampoline_start;
|
||||||
extern uint8_t ld_trampoline_end;
|
extern uint8_t ld_trampoline_end;
|
||||||
|
Loading…
Reference in New Issue
Block a user