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