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 / log.c
4.4 kB 164 lines
1#include "hv/arch.h" 2#include "hv/config.h" 3#include "hv/log.h" 4#include "hv/string.h" 5#include "hv/timer.h" 6#include "hv/uart.h" 7 8struct log_ring { 9 struct log_event events[CONFIG_LOG_CAPACITY]; 10 volatile unsigned lock; 11 uint64_t next_seq; 12 uint32_t write_index; 13 bool wrapped; 14}; 15 16static struct log_ring g_log; 17static struct log_ring g_log_selftest_backup; 18 19static void lock_log(void) 20{ 21 while (__atomic_test_and_set(&g_log.lock, __ATOMIC_ACQUIRE)) { 22 } 23} 24 25static void unlock_log(void) 26{ 27 __atomic_clear(&g_log.lock, __ATOMIC_RELEASE); 28} 29 30void log_init(void) 31{ 32 hv_memset(&g_log, 0, sizeof(g_log)); 33} 34 35void log_event_commit(const struct log_event *event) 36{ 37 if (event == (const struct log_event *)0) { 38 return; 39 } 40 41 uint64_t irq_flags = arch_irq_save(); 42 lock_log(); 43 struct log_event *slot = &g_log.events[g_log.write_index]; 44 *slot = *event; 45 slot->seq = g_log.next_seq++; 46 slot->cpu = arch_mpidr_el1() & 0xffu; 47 slot->timestamp = timer_now(); 48 g_log.write_index++; 49 if (g_log.write_index == CONFIG_LOG_CAPACITY) { 50 g_log.write_index = 0; 51 g_log.wrapped = true; 52 } 53 unlock_log(); 54 arch_irq_restore(irq_flags); 55} 56 57void log_simple(enum log_kind kind, uint32_t reason, uint64_t a, uint64_t b) 58{ 59 struct log_event ev; 60 hv_memset(&ev, 0, sizeof(ev)); 61 ev.kind = (uint32_t)kind; 62 ev.reason = reason; 63 ev.iss = a; 64 ev.elr = b; 65 log_event_commit(&ev); 66} 67 68static const char *kind_name(uint32_t kind) 69{ 70 switch (kind) { 71 case LOG_BOOT: return "boot"; 72 case LOG_TRAP: return "trap"; 73 case LOG_POLICY: return "policy"; 74 case LOG_HVC: return "hvc"; 75 case LOG_ABORT: return "abort"; 76 case LOG_MONITOR: return "monitor"; 77 case LOG_PANIC: return "panic"; 78 case LOG_SELFTEST: return "selftest"; 79 default: return "unknown"; 80 } 81} 82 83void log_dump(unsigned limit) 84{ 85 uint64_t irq_flags = arch_irq_save(); 86 lock_log(); 87 uint32_t count = g_log.wrapped ? CONFIG_LOG_CAPACITY : g_log.write_index; 88 if (limit != 0u && limit < count) { 89 count = limit; 90 } 91 92 uint32_t start = g_log.wrapped ? g_log.write_index : 0u; 93 if (g_log.wrapped && count < CONFIG_LOG_CAPACITY) { 94 start = (g_log.write_index + CONFIG_LOG_CAPACITY - count) % CONFIG_LOG_CAPACITY; 95 } 96 97 for (uint32_t i = 0; i < count; i++) { 98 const struct log_event *ev = &g_log.events[(start + i) % CONFIG_LOG_CAPACITY]; 99 uart_puts("event seq="); 100 uart_put_dec64(ev->seq); 101 uart_puts(" cpu="); 102 uart_put_dec64(ev->cpu); 103 uart_puts(" vcpu="); 104 uart_put_dec64(ev->vcpu); 105 uart_puts(" ts="); 106 uart_put_dec64(ev->timestamp); 107 uart_puts(" kind="); 108 uart_puts(kind_name(ev->kind)); 109 uart_puts(" ec="); 110 uart_put_hex64(ev->ec); 111 uart_puts(" iss="); 112 uart_put_hex64(ev->iss); 113 uart_puts(" elr="); 114 uart_put_hex64(ev->elr); 115 uart_puts(" far="); 116 uart_put_hex64(ev->far); 117 uart_puts(" hpfar="); 118 uart_put_hex64(ev->hpfar); 119 uart_puts(" sysreg="); 120 uart_put_hex64(ev->sysreg_key); 121 uart_puts(" name="); 122 uart_puts(ev->name != (const char *)0 ? ev->name : "-"); 123 uart_puts(" dir="); 124 uart_puts(ev->is_read != 0u ? "read" : "write"); 125 uart_puts(" rt="); 126 uart_put_dec64(ev->rt); 127 uart_puts(" operand="); 128 uart_put_hex64(ev->operand); 129 uart_puts(" result="); 130 uart_put_hex64(ev->result); 131 uart_puts(" action="); 132 uart_put_dec64(ev->action); 133 uart_puts(" pstate="); 134 uart_put_hex64(ev->pstate); 135 uart_puts(" reason="); 136 uart_put_dec64(ev->reason); 137 uart_puts("\n"); 138 } 139 unlock_log(); 140 arch_irq_restore(irq_flags); 141} 142 143void log_clear(void) 144{ 145 uint64_t irq_flags = arch_irq_save(); 146 lock_log(); 147 hv_memset(g_log.events, 0, sizeof(g_log.events)); 148 g_log.write_index = 0; 149 g_log.wrapped = false; 150 unlock_log(); 151 arch_irq_restore(irq_flags); 152} 153 154bool log_selftest(void) 155{ 156 g_log_selftest_backup = g_log; 157 log_init(); 158 for (uint32_t i = 0; i < CONFIG_LOG_CAPACITY + 3u; i++) { 159 log_simple(LOG_SELFTEST, i, i, i + 1u); 160 } 161 bool ok = g_log.wrapped && g_log.next_seq == (uint64_t)CONFIG_LOG_CAPACITY + 3u; 162 g_log = g_log_selftest_backup; 163 return ok; 164}