HV: separate linux loader from direct boot sw loader

Currently the algorithm of direct_boot_sw_loader() is Linux bzImage specific,
so separate the bzImage specific loader code from it to make the api more
generic for other OS;

Tracked-On: #3214

Signed-off-by: Victor Sun <victor.sun@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
This commit is contained in:
Victor Sun 2019-06-02 22:15:37 +08:00 committed by wenlingz
parent 0f00a4b0da
commit 1c00611382
1 changed files with 65 additions and 60 deletions

View File

@ -98,24 +98,16 @@ static uint64_t create_zero_page(struct acrn_vm *vm)
return gpa;
}
int32_t direct_boot_sw_loader(struct acrn_vm *vm)
static void prepare_loading_bzimage(struct acrn_vm *vm, struct acrn_vcpu *vcpu)
{
int32_t ret = 0;
uint32_t i;
char dyn_bootargs[100] = {0};
uint32_t kernel_entry_offset;
struct zero_page *zeropage;
struct sw_kernel_info *sw_kernel = &(vm->sw.kernel_info);
struct sw_module_info *bootargs_info = &(vm->sw.bootargs_info);
struct sw_module_info *ramdisk_info = &(vm->sw.ramdisk_info);
/* get primary vcpu */
struct acrn_vcpu *vcpu = vcpu_from_vid(vm, BOOT_CPU_ID);
const struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id);
pr_dbg("Loading guest to run-time location");
prepare_bsp_gdt(vm);
set_vcpu_regs(vcpu, &boot_context);
/* calculate the kernel entry point */
zeropage = (struct zero_page *)sw_kernel->kernel_src_addr;
stac();
@ -128,19 +120,6 @@ int32_t direct_boot_sw_loader(struct acrn_vm *vm)
sw_kernel->kernel_entry_addr = (void *)((uint64_t)sw_kernel->kernel_load_addr + kernel_entry_offset);
/* Set VCPU entry point to kernel entry */
vcpu_set_rip(vcpu, (uint64_t)sw_kernel->kernel_entry_addr);
pr_info("%s, VM %hu VCPU %hu Entry: 0x%016llx ", __func__, vm->vm_id, vcpu->vcpu_id,
sw_kernel->kernel_entry_addr);
/* Copy the guest kernel image to its run-time location */
(void)copy_to_gpa(vm, sw_kernel->kernel_src_addr,
(uint64_t)sw_kernel->kernel_load_addr, sw_kernel->kernel_size);
/* See if guest is a Linux guest */
if (vm->sw.kernel_type == VM_LINUX_GUEST) {
uint32_t i;
/* Documentation states: ebx=0, edi=0, ebp=0, esi=ptr to
* zeropage
*/
@ -164,12 +143,36 @@ int32_t direct_boot_sw_loader(struct acrn_vm *vm)
if (reserving_1g_pages > 0) {
snprintf(dyn_bootargs, 100U, " hugepagesz=1G hugepages=%lld", reserving_1g_pages);
(void)copy_to_gpa(vm, dyn_bootargs, ((uint64_t)bootargs_info->load_addr
+ bootargs_info->size),
(strnlen_s(dyn_bootargs, 99U) + 1U));
+ bootargs_info->size), (strnlen_s(dyn_bootargs, 99U) + 1U));
}
}
/* Check if a RAM disk is present with Linux guest */
/* Create Zeropage and copy Physical Base Address of Zeropage
* in RSI
*/
vcpu_set_gpreg(vcpu, CPU_REG_RSI, create_zero_page(vm));
pr_info("%s, RSI pointing to zero page for VM %d at GPA %X",
__func__, vm->vm_id, vcpu_get_gpreg(vcpu, CPU_REG_RSI));
}
int32_t direct_boot_sw_loader(struct acrn_vm *vm)
{
int32_t ret = 0;
struct sw_kernel_info *sw_kernel = &(vm->sw.kernel_info);
struct sw_module_info *ramdisk_info = &(vm->sw.ramdisk_info);
/* get primary vcpu */
struct acrn_vcpu *vcpu = vcpu_from_vid(vm, BOOT_CPU_ID);
pr_dbg("Loading guest to run-time location");
prepare_bsp_gdt(vm);
set_vcpu_regs(vcpu, &boot_context);
/* Copy the guest kernel image to its run-time location */
(void)copy_to_gpa(vm, sw_kernel->kernel_src_addr,
(uint64_t)sw_kernel->kernel_load_addr, sw_kernel->kernel_size);
/* Check if a RAM disk is present */
if (ramdisk_info->src_addr != NULL) {
/* Copy RAM disk to its load location */
(void)copy_to_gpa(vm, ramdisk_info->src_addr,
@ -177,18 +180,20 @@ int32_t direct_boot_sw_loader(struct acrn_vm *vm)
ramdisk_info->size);
}
/* Create Zeropage and copy Physical Base Address of Zeropage
* in RSI
*/
vcpu_set_gpreg(vcpu, CPU_REG_RSI, create_zero_page(vm));
pr_info("%s, RSI pointing to zero page for VM %d at GPA %X",
__func__, vm->vm_id, vcpu_get_gpreg(vcpu, CPU_REG_RSI));
/* See if guest is a Linux guest */
if (vm->sw.kernel_type == VM_LINUX_GUEST) {
prepare_loading_bzimage(vm, vcpu);
} else {
pr_err("%s, Loading VM SW failed", __func__);
ret = -EINVAL;
}
if (ret == 0) {
/* Set VCPU entry point to kernel entry */
vcpu_set_rip(vcpu, (uint64_t)sw_kernel->kernel_entry_addr);
pr_info("%s, VM %hu VCPU %hu Entry: 0x%016llx ", __func__, vm->vm_id, vcpu->vcpu_id,
sw_kernel->kernel_entry_addr);
}
return ret;
}