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