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.8 kB 119 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 29bool platform_selftest(void) 30{ 31 return CONFIG_PLATFORM_QEMU_VIRT == 1 && 32 CONFIG_UART_BASE == 0x09000000ull && 33 CONFIG_GICD_BASE == 0x08000000ull && 34 CONFIG_GICR_BASE == 0x080A0000ull && 35 CONFIG_GUEST_IPA_BASE == 0x40000000ull && 36 CONFIG_GUEST_RAM_BASE == 0x42000000ull && 37 CONFIG_GUEST_RAM_SIZE == 0x30000000ull && 38 CONFIG_LINUX_DTB_PA == 0x71e00000ull; 39} 40 41static void print_banner(void) 42{ 43 uart_puts("\n"); 44 uart_puts(HV_PROJECT_NAME " " HV_BUILD_MODE "\n"); 45 uart_puts("build id=" HV_BUILD_ID "\n"); 46} 47 48void hv_main(uint64_t boot_dtb_pa) 49{ 50 struct guest_image_info guest_info; 51 52 uart_init(); 53 print_banner(); 54 log_init(); 55 timer_init(); 56 monitor_init(); 57 58 if (arch_current_el() != 2u) { 59 panic_with_code("hypervisor must start at EL2", arch_current_el()); 60 } 61 if (fdt_probe(boot_dtb_pa, &g_platform_info)) { 62 log_simple(LOG_BOOT, 30u, g_platform_info.fdt_pa, g_platform_info.size); 63 } else { 64 hv_memset(&g_platform_info, 0, sizeof(g_platform_info)); 65 log_simple(LOG_BOOT, 31u, boot_dtb_pa, 0u); 66 } 67 68 arch_install_vectors(); 69 el2_mmu_init_plan(); 70 el2_mmu_enable(); 71 allocator_init((paddr_t)(uintptr_t)g_allocator_pool, sizeof(g_allocator_pool)); 72 policy_init(); 73#if CONFIG_BOOT_LINUX 74 (void)policy_set_profile(POLICY_PROFILE_LINUX_BOOT); 75#endif 76 stage2_init(); 77#if CONFIG_BOOT_LINUX 78 if (!guest_load_external_linux(&guest_info, CONFIG_LINUX_IMAGE_LOAD_PA, 79 CONFIG_LINUX_IMAGE_MAX_SIZE, CONFIG_LINUX_DTB_PA, 80 CONFIG_LINUX_DTB_MAX_SIZE, CONFIG_LINUX_INITRD_PA, 81 CONFIG_LINUX_INITRD_SIZE)) { 82 panic("external Linux Image load failed"); 83 } 84#else 85 if (!guest_load_diagnostic(&guest_info)) { 86 panic("diagnostic guest load failed"); 87 } 88#endif 89 log_simple(LOG_BOOT, 10u, guest_info.ipa_load, guest_info.size); 90 if (!stage2_map_range(CONFIG_GUEST_IPA_BASE, CONFIG_GUEST_RAM_BASE, CONFIG_GUEST_RAM_SIZE, 91 S2_MEM_NORMAL, S2_PERM_R | S2_PERM_W | S2_PERM_X)) { 92 panic("stage2 guest RAM map failed"); 93 } 94 95 gicv3_init(); 96 arch_el2_configure(stage2_vttbr(), stage2_vtcr()); 97 selftests_run_or_panic(); 98 99 vcpu_init(&g_boot_vcpu, 0u, guest_info.ipa_entry, CONFIG_GUEST_STACK_TOP); 100 vcpu_set_current(&g_boot_vcpu); 101 arch_prepare_guest_entry(&g_boot_vcpu); 102 if (guest_info.kind == GUEST_PAYLOAD_LINUX_IMAGE) { 103 vcpu_write_gpr(&g_boot_vcpu, 0u, guest_info.dtb_ipa); 104 vcpu_write_gpr(&g_boot_vcpu, 1u, 0u); 105 vcpu_write_gpr(&g_boot_vcpu, 2u, 0u); 106 vcpu_write_gpr(&g_boot_vcpu, 3u, 0u); 107 } 108 109 uart_puts("launching guest entry="); 110 uart_put_hex64(g_boot_vcpu.pc); 111 uart_puts(" stack="); 112 uart_put_hex64(g_boot_vcpu.sp_el1); 113 uart_puts("\n"); 114 g_boot_vcpu.state = VCPU_RUNNING; 115 timer_vcpu_sync(&g_boot_vcpu); 116 gicv3_flush_vcpu_state(&g_boot_vcpu); 117 arch_vcpu_enter(&g_boot_vcpu); 118 panic("arch_vcpu_enter returned"); 119}