1 // © 2021 Qualcomm Innovation Center, Inc. All rights reserved.
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4
5 #include <assert.h>
6 #include <hyptypes.h>
7 #include <string.h>
8
9 #include <atomic.h>
10 #include <hyp_aspace.h>
11 #include <panic.h>
12 #include <partition.h>
13 #include <pgtable.h>
14 #include <preempt.h>
15 #include <spinlock.h>
16
17 #include "event_handlers.h"
18 #include "uart.h"
19
20 static soc_qemu_uart_t *uart;
21 static spinlock_t uart_lock;
22
23 static void
uart_putc(const char c)24 uart_putc(const char c)
25 {
26 while ((atomic_load_relaxed(&uart->tfr) & ((uint32_t)1U << 5)) != 0U) {
27 }
28
29 atomic_store_relaxed(&uart->dr, c);
30 }
31
32 static char *banner = "[HYP] ";
33
34 static void
uart_write(const char * out,size_t size)35 uart_write(const char *out, size_t size)
36 {
37 size_t remain = size;
38 const char *pos = out;
39
40 for (size_t i = 0; i < strlen(banner); i++) {
41 uart_putc(banner[i]);
42 }
43
44 while (remain > 0) {
45 char c;
46
47 if (*pos == '\n') {
48 c = '\r';
49 uart_putc(c);
50 }
51
52 c = *pos;
53 uart_putc(c);
54 pos++;
55 remain--;
56 }
57
58 uart_putc('\n');
59 }
60
61 void
soc_qemu_console_puts(const char * msg)62 soc_qemu_console_puts(const char *msg)
63 {
64 spinlock_acquire(&uart_lock);
65 if (uart != NULL) {
66 uart_write(msg, strlen(msg));
67 }
68 spinlock_release(&uart_lock);
69 }
70
71 void
soc_qemu_handle_log_message(trace_id_t id,const char * str)72 soc_qemu_handle_log_message(trace_id_t id, const char *str)
73 {
74 #if defined(VERBOSE) && VERBOSE
75 (void)id;
76
77 soc_qemu_console_puts(str);
78 #else
79 if ((id == TRACE_ID_WARN) || (id == TRACE_ID_PANIC) ||
80 (id == TRACE_ID_ASSERT_FAILED) ||
81 #if defined(INTERFACE_TESTS)
82 (id == TRACE_ID_TEST) ||
83 #endif
84 (id == TRACE_ID_DEBUG)) {
85 soc_qemu_console_puts(str);
86 }
87 #endif
88 }
89
90 void
soc_qemu_uart_init(void)91 soc_qemu_uart_init(void)
92 {
93 spinlock_init(&uart_lock);
94
95 virt_range_result_t range = hyp_aspace_allocate(PLATFORM_UART_SIZE);
96 if (range.e != OK) {
97 panic("uart: Address allocation failed.");
98 }
99
100 pgtable_hyp_start();
101
102 // Map UART
103 uart = (soc_qemu_uart_t *)range.r.base;
104 error_t ret = pgtable_hyp_map(partition_get_private(), (uintptr_t)uart,
105 PLATFORM_UART_SIZE, PLATFORM_UART_BASE,
106 PGTABLE_HYP_MEMTYPE_NOSPEC_NOCOMBINE,
107 PGTABLE_ACCESS_RW,
108 VMSA_SHAREABILITY_NON_SHAREABLE);
109 if (ret != OK) {
110 panic("uart: Mapping failed.");
111 }
112
113 pgtable_hyp_commit();
114 }
115