AArch64 EL2 hypervisor for QEMU virt that boots at EL2
1

Configure Feed

Select the types of activity you want to include in your feed.

ariel / core / main.c
3.3 kB 107 lines
1#include "hv/allocator.h" 2#include "hv/arch.h" 3#include "hv/config.h" 4#include "hv/el2_mmu.h" 5#include "hv/fdt.h" 6#include "hv/gicv3.h" 7#include "hv/guest_loader.h" 8#include "hv/log.h" 9#include "hv/monitor.h" 10#include "hv/panic.h" 11#include "hv/platform.h" 12#include "hv/policy.h" 13#include "hv/selftest.h" 14#include "hv/stage2.h" 15#include "hv/string.h" 16#include "hv/timer.h" 17#include "hv/uart.h" 18#include "hv/vcpu.h" 19 20static struct vcpu g_boot_vcpu; 21static uint8_t g_allocator_pool[CONFIG_PAGE_SIZE * 16u] __attribute__((aligned(4096))); 22static struct fdt_platform_info g_platform_info; 23 24const struct fdt_platform_info *platform_info(void) 25{ 26 return &g_platform_info; 27} 28 29static void print_banner(void) 30{ 31 uart_puts("\n"); 32 uart_puts(HV_PROJECT_NAME " " HV_BUILD_MODE "\n"); 33 uart_puts("build id=" HV_BUILD_ID "\n"); 34} 35 36void hv_main(uint64_t boot_dtb_pa) 37{ 38 struct guest_image_info guest_info; 39 40 uart_init(); 41 print_banner(); 42 log_init(); 43 timer_init(); 44 monitor_init(); 45 46 if (arch_current_el() != 2u) { 47 panic_with_code("hypervisor must start at EL2", arch_current_el()); 48 } 49 if (fdt_probe(boot_dtb_pa, &g_platform_info)) { 50 log_simple(LOG_BOOT, 30u, g_platform_info.fdt_pa, g_platform_info.size); 51 } else { 52 hv_memset(&g_platform_info, 0, sizeof(g_platform_info)); 53 log_simple(LOG_BOOT, 31u, boot_dtb_pa, 0u); 54 } 55 56 arch_install_vectors(); 57 el2_mmu_init_plan(); 58 el2_mmu_enable(); 59 allocator_init((paddr_t)(uintptr_t)g_allocator_pool, sizeof(g_allocator_pool)); 60 policy_init(); 61#if CONFIG_BOOT_LINUX 62 (void)policy_set_profile(POLICY_PROFILE_LINUX_BOOT); 63#endif 64 stage2_init(); 65#if CONFIG_BOOT_LINUX 66 if (!guest_load_external_linux(&guest_info, CONFIG_LINUX_IMAGE_LOAD_PA, 67 CONFIG_LINUX_IMAGE_MAX_SIZE, CONFIG_LINUX_DTB_PA, 68 CONFIG_LINUX_DTB_MAX_SIZE, CONFIG_LINUX_INITRD_PA, 69 CONFIG_LINUX_INITRD_SIZE)) { 70 panic("external Linux Image load failed"); 71 } 72#else 73 if (!guest_load_diagnostic(&guest_info)) { 74 panic("diagnostic guest load failed"); 75 } 76#endif 77 log_simple(LOG_BOOT, 10u, guest_info.ipa_load, guest_info.size); 78 if (!stage2_map_range(CONFIG_GUEST_IPA_BASE, CONFIG_GUEST_RAM_BASE, CONFIG_GUEST_RAM_SIZE, 79 S2_MEM_NORMAL, S2_PERM_R | S2_PERM_W | S2_PERM_X)) { 80 panic("stage2 guest RAM map failed"); 81 } 82 83 gicv3_init(); 84 arch_el2_configure(stage2_vttbr(), stage2_vtcr()); 85 selftests_run_or_panic(); 86 87 vcpu_init(&g_boot_vcpu, 0u, guest_info.ipa_entry, CONFIG_GUEST_STACK_TOP); 88 vcpu_set_current(&g_boot_vcpu); 89 arch_prepare_guest_entry(&g_boot_vcpu); 90 if (guest_info.kind == GUEST_PAYLOAD_LINUX_IMAGE) { 91 vcpu_write_gpr(&g_boot_vcpu, 0u, guest_info.dtb_ipa); 92 vcpu_write_gpr(&g_boot_vcpu, 1u, 0u); 93 vcpu_write_gpr(&g_boot_vcpu, 2u, 0u); 94 vcpu_write_gpr(&g_boot_vcpu, 3u, 0u); 95 } 96 97 uart_puts("launching guest entry="); 98 uart_put_hex64(g_boot_vcpu.pc); 99 uart_puts(" stack="); 100 uart_put_hex64(g_boot_vcpu.sp_el1); 101 uart_puts("\n"); 102 g_boot_vcpu.state = VCPU_RUNNING; 103 timer_vcpu_sync(&g_boot_vcpu); 104 gicv3_flush_vcpu_state(&g_boot_vcpu); 105 arch_vcpu_enter(&g_boot_vcpu); 106 panic("arch_vcpu_enter returned"); 107}