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 / README.md
3.2 kB 147 lines
1# ariel 2 3AArch64 EL2 hypervisor for QEMU virt that boots at EL2, sets up exception vectors, writes a stage 2 guest IPA space and loads a bundled EL1 diagnostic guest/an external linux image and traps privileged guest activity as well as applying compiled policy tables and exposes a UART monitor over QEMU stdio 4 5## Build/Run 6 7```sh 8make clean 9make 10``` 11 12```sh 13make run 14``` 15 16Equivalent QEMU shape 17 18```sh 19qemu-system-aarch64 \ 20 -M virt,virtualization=on,gic-version=3 \ 21 -cpu cortex-a57 \ 22 -m 1G \ 23 -nographic \ 24 -serial mon:stdio \ 25 -kernel build/hypervisor.elf 26``` 27 28Run a Linux arm64 `Image` with a QEMU `virt` DTB 29 30```sh 31make run-linux \ 32 LINUX_IMAGE=/path/Image \ 33 LINUX_DTB=/path/qemu-virt.dtb 34``` 35 36Or just do it with an initrd 37 38```sh 39make run-linux \ 40 LINUX_IMAGE=/path/Image \ 41 LINUX_DTB=/path/qemu-virt.dtb \ 42 LINUX_INITRD=/path/initrd.gz 43``` 44 45Fetch the tested Debian installer artifacts and smoke test the Linux path 46 47```sh 48make test-linux-smoke 49``` 50and complete the local gate 51 52```sh 53make test 54make release 55``` 56 57## Memory 58 59```text 60hypervisor link PA 0x40080000 61guest IPA base 0x40000000 62guest backing PA 0x42000000 63guest RAM size 0x30000000 768 MiB 64diagnostic entry IPA 0x40000000 65diagnostic stack top 0x40100000 66Linux Image load PA 0x42000000 67Linux Image entry IPA Image text_offset + 0x40000000 68Linux initrd PA 0x46000000 69Linux initrd IPA 0x44000000 70Linux DTB PA 0x71e00000 71Linux DTB IPA 0x6fe00000 72PL011 UART PA 0x09000000 73GICD PA 0x08000000 74GICR PA 0x080a0000 75``` 76 77S2 uses 2 MiB block mappings for guest RAM. The guest sees the IPA range `0x40000000..0x70000000` which EL2 maps onto the PA range `0x42000000..0x72000000`. MMIO isn't passed through by default andkKnown device ranges are handled through policy or emulation layers 78 79## Trap Path 80 81EL1 traps enter the EL2 vector table and the assembly path saves general registers and exception state into `struct trap_frame` 82 83```text 84x0-x30 85sp_el0 86sp_el1 87elr_el2 88spsr_el2 89esr_el2 90far_el2 91hpfar_el2 92``` 93 94## Hypercalls 95 96 97```c 98enum { 99 HVC_GET_HV_ID = 0, 100 HVC_DUMP_LOG = 1, 101 HVC_GET_STATUS = 2, 102 HVC_PAUSE = 3, 103 HVC_GUEST_CONSOLE_WRITE = 4, 104 HVC_REPORT_EXCEPTION = 5, 105}; 106``` 107 108Guest side call pattern 109 110```c 111static inline unsigned long hvc(unsigned long op, 112 unsigned long a1, 113 unsigned long a2, 114 unsigned long a3) 115{ 116 register unsigned long x0 asm("x0") = op; 117 register unsigned long x1 asm("x1") = a1; 118 register unsigned long x2 asm("x2") = a2; 119 register unsigned long x3 asm("x3") = a3; 120 121 asm volatile("hvc #0" 122 : "+r"(x0) 123 : "r"(x1), "r"(x2), "r"(x3) 124 : "memory"); 125 return x0; 126} 127``` 128 129Console write from guest IPA memory 130 131```c 132const char msg[] = "guest online"; 133hvc(HVC_GUEST_CONSOLE_WRITE, (unsigned long)msg, sizeof(msg) - 1, 0); 134``` 135 136Pause into the EL2 monitor: 137 138```c 139hvc(HVC_PAUSE, 0, 0, 0); 140``` 141 142## Logs 143 144```sh 145make run 2>&1 | tee uart.log 146python3 tools/log_decode.py --summary < uart.log 147```