Files
acrn-hypervisor/hypervisor/bsp/uefi/uefi.c
Binbin Wu 33e1149b29 hv: init: unify init logic for vm0 bsp
In current code, VM0 BSP start mode is hardcoded, in this patch VM0 BSP
start mode is decided by the boot context prepared by bootloader/BIOS.

In current code, VM0 BSP VMCS is override only on UEFI platform.
In this patch, VM0 BSP VMCS is override on both SBL & UEFI platforms.

Also restructure the code of guest init code.
In this patch, a vcpu run_context is initilaized first according to vcpu mode.
Then write the value to vmcs according to run_context value.

Signed-off-by: Binbin Wu <binbin.wu@intel.com>
Reviewed-by: Jason Chen CJ <jason.cj.chen@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
2018-08-09 16:43:58 +08:00

124 lines
2.5 KiB
C

/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <hypervisor.h>
#include <multiboot.h>
#include <vm0_boot.h>
/* IOAPIC id */
#define UEFI_IOAPIC_ID 8
/* IOAPIC base address */
#define UEFI_IOAPIC_ADDR 0xfec00000
/* IOAPIC range size */
#define UEFI_IOAPIC_SIZE 0x100000
/* Local APIC base address */
#define UEFI_LAPIC_ADDR 0xfee00000
/* Local APIC range size */
#define UEFI_LAPIC_SIZE 0x100000
/* Number of PCI IRQ assignments */
#define UEFI_PCI_IRQ_ASSIGNMENT_NUM 28
#ifdef CONFIG_EFI_STUB
static void efi_init(void);
struct boot_ctx* efi_ctx = NULL;
struct lapic_regs uefi_lapic_regs;
static int efi_initialized;
void efi_spurious_handler(int vector)
{
struct vcpu* vcpu;
int ret;
if (get_cpu_id() != 0)
return;
vcpu = per_cpu(vcpu, 0);
if ((vcpu != NULL) && vcpu->arch_vcpu.vlapic) {
ret = vlapic_set_intr(vcpu, vector, 0);
if (ret != 0)
pr_err("%s vlapic set intr fail, interrupt lost\n",
__func__);
} else
pr_err("%s vcpu or vlapic is not ready, interrupt lost\n",
__func__);
return;
}
int uefi_sw_loader(struct vm *vm, struct vcpu *vcpu)
{
int ret = 0;
struct run_context *cur_context =
&vcpu->arch_vcpu.contexts[vcpu->arch_vcpu.cur_context].run_ctx;
ASSERT(vm != NULL, "Incorrect argument");
pr_dbg("Loading guest to run-time location");
if (!is_vm0(vm))
return load_guest(vm, vcpu);
vlapic_restore(vcpu->arch_vcpu.vlapic, &uefi_lapic_regs);
vcpu->entry_addr = (void *)efi_ctx->rip;
memcpy_s(&cur_context->guest_cpu_regs, sizeof(struct cpu_gp_regs),
&efi_ctx->gprs, sizeof(struct cpu_gp_regs));
/* defer irq enabling till vlapic is ready */
CPU_IRQ_ENABLE();
return ret;
}
void *get_rsdp_from_uefi(void)
{
if (!efi_initialized)
efi_init();
return HPA2HVA(efi_ctx->rsdp);
}
void *get_ap_trampoline_buf(void)
{
return efi_ctx->ap_trampoline_buf;
}
static void efi_init(void)
{
struct multiboot_info *mbi = NULL;
if (boot_regs[0] != MULTIBOOT_INFO_MAGIC)
ASSERT(0, "no multiboot info found");
mbi = (struct multiboot_info *)HPA2HVA(((uint64_t)(uint32_t)boot_regs[1]));
if (!(mbi->mi_flags & MULTIBOOT_INFO_HAS_DRIVES))
ASSERT(0, "no multiboot drivers for uefi found");
efi_ctx = (struct boot_ctx *)HPA2HVA((uint64_t)mbi->mi_drives_addr);
ASSERT(efi_ctx != NULL, "no uefi context found");
vm_sw_loader = uefi_sw_loader;
spurious_handler = efi_spurious_handler;
save_lapic(&uefi_lapic_regs);
efi_initialized = 1;
}
#endif
void init_bsp(void)
{
parse_hv_cmdline();
#ifdef CONFIG_EFI_STUB
if (!efi_initialized)
efi_init();
#endif
}