mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-11-22 23:57:47 +00:00
hv: risc-v: add relocation support
This patch implements relocation support for ACRN RISC-V to enable position-independent execution. The hypervisor can now be loaded at any physical address and will automatically relocate itself at runtime. Key changes: - Add relocate() function to process R_RISCV_RELATIVE relocations in .rela sections during early boot - Implement arch_get_hv_image_delta() to calculate the load address offset from the configured base address - Add relocation processing in cpu_entry.S before jumping to C code - Update linker script to include .rela sections for relocation data - Define R_RISCV_RELATIVE relocation type and linker symbol definitions Tracked-On: #8825 Signed-off-by: Jian Jun Chen <jian.jun.chen@intel.com> Acked-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
committed by
acrnsi-robot
parent
f904dbffbb
commit
1dee977429
@@ -42,6 +42,7 @@ HOST_S_SRCS += arch/riscv/intr.S
|
|||||||
HOST_S_SRCS += arch/riscv/sched.S
|
HOST_S_SRCS += arch/riscv/sched.S
|
||||||
|
|
||||||
# HV host C sources
|
# HV host C sources
|
||||||
|
HOST_C_SRCS += arch/riscv/boot/reloc.c
|
||||||
HOST_C_SRCS += arch/riscv/init.c
|
HOST_C_SRCS += arch/riscv/init.c
|
||||||
HOST_C_SRCS += arch/riscv/sbi.c
|
HOST_C_SRCS += arch/riscv/sbi.c
|
||||||
HOST_C_SRCS += arch/riscv/notify.c
|
HOST_C_SRCS += arch/riscv/notify.c
|
||||||
|
|||||||
@@ -38,6 +38,15 @@ _clear_bss:
|
|||||||
/* Setup cpu0 boot stack (full descending) */
|
/* Setup cpu0 boot stack (full descending) */
|
||||||
lla sp, _boot_stack_end
|
lla sp, _boot_stack_end
|
||||||
|
|
||||||
|
#ifdef CONFIG_RELOC
|
||||||
|
mv s1, a0
|
||||||
|
lla a0, _DYNAMIC
|
||||||
|
|
||||||
|
/* Fix up the .rela sections */
|
||||||
|
call relocate
|
||||||
|
mv a0, s1
|
||||||
|
#endif /* CONFIG_RELOC */
|
||||||
|
|
||||||
/* a0 = hart_id, a1 = dtb_address */
|
/* a0 = hart_id, a1 = dtb_address */
|
||||||
tail init_primary_pcpu
|
tail init_primary_pcpu
|
||||||
|
|
||||||
|
|||||||
73
hypervisor/arch/riscv/boot/reloc.c
Normal file
73
hypervisor/arch/riscv/boot/reloc.c
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Intel Corporation.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <reloc.h>
|
||||||
|
|
||||||
|
/* get the delta between CONFIG_HV_RAM_START and the actual load address */
|
||||||
|
uint64_t arch_get_hv_image_delta(void)
|
||||||
|
{
|
||||||
|
uint64_t delta;
|
||||||
|
|
||||||
|
asm volatile (
|
||||||
|
"lla %0, _start\n"
|
||||||
|
"li t1, %1\n"
|
||||||
|
"sub %0, %0, t1\n"
|
||||||
|
: "=r" (delta)
|
||||||
|
: "i" ((uint64_t)CONFIG_HV_RAM_START)
|
||||||
|
: "t1");
|
||||||
|
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_RELOC
|
||||||
|
void relocate(struct Elf64_Dyn *dynamic)
|
||||||
|
{
|
||||||
|
struct Elf64_Dyn *dyn;
|
||||||
|
struct Elf64_Rel *entry = NULL;
|
||||||
|
uint8_t *rela_start = NULL, *rela_end = NULL;
|
||||||
|
uint64_t rela_size = 0;
|
||||||
|
uint64_t delta, entry_size = 0;
|
||||||
|
uint64_t *addr;
|
||||||
|
|
||||||
|
/* get the delta that needs to be patched */
|
||||||
|
delta = get_hv_image_delta();
|
||||||
|
/* Look for the descriptoin of relocation sections */
|
||||||
|
for (dyn = (struct Elf64_Dyn *)dynamic;
|
||||||
|
dyn->d_tag != DT_NULL; dyn++) {
|
||||||
|
switch (dyn->d_tag) {
|
||||||
|
case DT_RELA:
|
||||||
|
rela_start = (uint8_t *)(dyn->d_ptr + delta);
|
||||||
|
break;
|
||||||
|
case DT_RELASZ:
|
||||||
|
rela_size = dyn->d_ptr;
|
||||||
|
break;
|
||||||
|
case DT_RELAENT:
|
||||||
|
entry_size = dyn->d_ptr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* if no RELA/RELASZ found, both start and end will be
|
||||||
|
* initialized to NULL, and later while loop won't be executed
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to subtract the relocation delta to get the correct
|
||||||
|
* absolute addresses
|
||||||
|
*/
|
||||||
|
rela_end = rela_start + rela_size;
|
||||||
|
while (rela_start < rela_end) {
|
||||||
|
entry = (struct Elf64_Rel *)rela_start;
|
||||||
|
if ((elf64_r_type(entry->r_info)) == R_RISCV_RELATIVE) {
|
||||||
|
addr = (uint64_t *)(delta + entry->r_offset);
|
||||||
|
*addr += (entry->r_addend + delta);
|
||||||
|
}
|
||||||
|
rela_start += entry_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_RELOC */
|
||||||
@@ -10,7 +10,7 @@ ENTRY(_start)
|
|||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = CONFIG_HV_RAM_START;
|
. = CONFIG_HV_RAM_START;
|
||||||
_code_start = .;
|
ld_ram_start = .;
|
||||||
|
|
||||||
.text :
|
.text :
|
||||||
{
|
{
|
||||||
@@ -39,6 +39,14 @@ SECTIONS
|
|||||||
_rodata_end = .;
|
_rodata_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
. = ALIGN(0x1000);
|
||||||
|
.rela :
|
||||||
|
{
|
||||||
|
*(.rela)
|
||||||
|
*(.rela.*)
|
||||||
|
*(.dyn*)
|
||||||
|
}
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
. = ALIGN(0x1000);
|
||||||
.data :
|
.data :
|
||||||
{
|
{
|
||||||
@@ -80,5 +88,5 @@ SECTIONS
|
|||||||
}
|
}
|
||||||
|
|
||||||
. = ALIGN(0x1000);
|
. = ALIGN(0x1000);
|
||||||
_code_end = .;
|
ld_ram_end = .;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,4 +188,7 @@ static inline uint64_t elf64_r_type(uint64_t i)
|
|||||||
/* x86-64 relocation types */
|
/* x86-64 relocation types */
|
||||||
#define R_X86_64_RELATIVE 8U
|
#define R_X86_64_RELATIVE 8U
|
||||||
|
|
||||||
|
/* RISC-V relocation types */
|
||||||
|
#define R_RISCV_RELATIVE 3U
|
||||||
|
|
||||||
#endif /* !ELF_H */
|
#endif /* !ELF_H */
|
||||||
|
|||||||
25
hypervisor/include/arch/riscv/asm/boot/ld_sym.h
Normal file
25
hypervisor/include/arch/riscv/asm/boot/ld_sym.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 Intel Corporation.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LD_SYM_H
|
||||||
|
#define LD_SYM_H
|
||||||
|
|
||||||
|
extern const char _text_start;
|
||||||
|
extern const char _text_end;
|
||||||
|
|
||||||
|
extern const char _rodata_start;
|
||||||
|
extern const char _rodata_end;
|
||||||
|
|
||||||
|
extern char _data_start;
|
||||||
|
extern char _data_end;
|
||||||
|
|
||||||
|
extern char _bss_start;
|
||||||
|
extern char _bss_end;
|
||||||
|
|
||||||
|
extern char ld_ram_start;
|
||||||
|
extern char ld_ram_end;
|
||||||
|
|
||||||
|
#endif /* LD_SYM_H */
|
||||||
Reference in New Issue
Block a user