From 0579fe3f0a9675bbcbaa53331c7c1c3458f33232 Mon Sep 17 00:00:00 2001 From: Stephany Gamiz Date: Thu, 20 May 2021 14:18:00 +1000 Subject: [PATCH] soc_qemu: Add UART support This commit adds support for QEMU's UART. All messages added using LOG() or TRACE_AND_LOG() will now appear in console. Signed-off-by: Carl van Schaik --- hyp/platform/soc_qemu/build.conf | 5 +- hyp/platform/soc_qemu/include/uart.h | 6 ++ hyp/platform/soc_qemu/soc_qemu.ev | 5 ++ hyp/platform/soc_qemu/soc_qemu.tc | 7 ++ hyp/platform/soc_qemu/src/boot.c | 19 +++++ hyp/platform/soc_qemu/src/uart.c | 110 +++++++++++++++++++++++++++ 6 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 hyp/platform/soc_qemu/include/uart.h create mode 100644 hyp/platform/soc_qemu/src/uart.c diff --git a/hyp/platform/soc_qemu/build.conf b/hyp/platform/soc_qemu/build.conf index a5005a6..f78defd 100644 --- a/hyp/platform/soc_qemu/build.conf +++ b/hyp/platform/soc_qemu/build.conf @@ -7,7 +7,8 @@ configs BOOT_STACK_SIZE=6144 configs PLATFORM_IPI_LINES=8 base_module hyp/platform/gicv3 base_module hyp/platform/psci_smc -source boot.c cpu.c irq.c platform_psci.c prng.c soc_qemu.c head.S +local_include +source boot.c cpu.c irq.c platform_psci.c prng.c soc_qemu.c head.S uart.c types soc_qemu.tc events soc_qemu.ev @@ -16,5 +17,7 @@ configs PLATFORM_DEBUG_SAVE_STATE=2 arch_configs qemu PLATFORM_DEVICES_BASE=0x0U PLATFORM_DEVICES_SIZE=0x40000000U +arch_configs qemu PLATFORM_UART_BASE=0x9000000U PLATFORM_UART_SIZE=0x1000U + # This config variable has been added here since there is no trace unit configs VCPU_TRACE_CONTEXT_SAVED=1 diff --git a/hyp/platform/soc_qemu/include/uart.h b/hyp/platform/soc_qemu/include/uart.h new file mode 100644 index 0000000..79c6a35 --- /dev/null +++ b/hyp/platform/soc_qemu/include/uart.h @@ -0,0 +1,6 @@ +// © 2021 Qualcomm Innovation Center, Inc. All rights reserved. +// +// SPDX-License-Identifier: BSD-3-Clause + +void +soc_qemu_console_puts(const char *msg); diff --git a/hyp/platform/soc_qemu/soc_qemu.ev b/hyp/platform/soc_qemu/soc_qemu.ev index 3ad02e1..936abc6 100644 --- a/hyp/platform/soc_qemu/soc_qemu.ev +++ b/hyp/platform/soc_qemu/soc_qemu.ev @@ -9,6 +9,11 @@ subscribe rootvm_init(root_partition, root_cspace, env_data) subscribe boot_cpu_cold_init +subscribe boot_cold_init + handler soc_qemu_uart_init() + #if !defined(UNIT_TESTS) subscribe vcpu_activate_thread #endif + +subscribe log_message diff --git a/hyp/platform/soc_qemu/soc_qemu.tc b/hyp/platform/soc_qemu/soc_qemu.tc index b488795..650ba61 100644 --- a/hyp/platform/soc_qemu/soc_qemu.tc +++ b/hyp/platform/soc_qemu/soc_qemu.tc @@ -10,6 +10,8 @@ extend boot_env_data structure { hlos_vm_size size; hlos_dt_base type vmaddr_t; hlos_ramfs_base type vmaddr_t; + uart_me_capid type cap_id_t; + uart_address type paddr_t; }; #if defined (PLATFORM_PSCI_USE_ORIGINAL_POWERSTATE_FORMAT) @@ -25,3 +27,8 @@ define psci_suspend_powerstate_stateid bitfield<16> { #endif define psci_cpu_state_t newtype uint8; + +define soc_qemu_uart structure(aligned(PGTABLE_HYP_PAGE_SIZE)) { + dr @0x0 uint32(atomic); + tfr @0x18 uint32(atomic); +}; diff --git a/hyp/platform/soc_qemu/src/boot.c b/hyp/platform/soc_qemu/src/boot.c index fa21cc5..9c1b29b 100644 --- a/hyp/platform/soc_qemu/src/boot.c +++ b/hyp/platform/soc_qemu/src/boot.c @@ -192,5 +192,24 @@ soc_qemu_handle_rootvm_init(partition_t *root_partition, cspace_t *root_cspace, if (me_ret.e != OK) { panic("Failed creation of gicr memextent"); } + + // Derive extent for UART and share it with RM + me_ret = memextent_derive(me, PLATFORM_UART_BASE, PLATFORM_UART_SIZE, + MEMEXTENT_MEMTYPE_DEVICE, PGTABLE_ACCESS_RW); + if (me_ret.e != OK) { + panic("Failed creation of uart memextent"); + } + + // Create a master cap for the uart memextent + object_ptr_t obj_ptr; + obj_ptr.memextent = me_ret.r; + cap_id_result_t capid_ret = cspace_create_master_cap( + root_cspace, obj_ptr, OBJECT_TYPE_MEMEXTENT); + if (capid_ret.e != OK) { + panic("Error create memextent cap id."); + } + + env_data->uart_address = PLATFORM_UART_BASE; + env_data->uart_me_capid = capid_ret.r; } #endif diff --git a/hyp/platform/soc_qemu/src/uart.c b/hyp/platform/soc_qemu/src/uart.c new file mode 100644 index 0000000..8eff177 --- /dev/null +++ b/hyp/platform/soc_qemu/src/uart.c @@ -0,0 +1,110 @@ +// © 2021 Qualcomm Innovation Center, Inc. All rights reserved. +// +// SPDX-License-Identifier: BSD-3-Clause + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "event_handlers.h" +#include "uart.h" + +static soc_qemu_uart_t *uart; + +static void +uart_putc(const char c) +{ + while ((atomic_load_relaxed(&uart->tfr) & ((uint32_t)1U << 5)) != 0U) + ; + + atomic_store_relaxed(&uart->dr, c); +} + +static char *banner = "[HYP] "; + +static void +uart_write(const char *out, size_t size) +{ + size_t remain = size; + const char *pos = out; + + for (size_t i = 0; i < strlen(banner); i++) { + uart_putc(banner[i]); + } + + while (remain > 0) { + char c; + + if (*pos == '\n') { + c = '\r'; + uart_putc(c); + } + + c = *pos; + uart_putc(c); + pos++; + remain--; + } + + uart_putc('\n'); +} + +void +soc_qemu_console_puts(const char *msg) +{ + preempt_disable(); + if (uart != NULL) { + uart_write(msg, strlen(msg)); + } + preempt_enable(); +} + +void +soc_qemu_handle_log_message(trace_id_t id, const char *str) +{ +#if defined(VERBOSE) && VERBOSE + (void)id; + + soc_qemu_console_puts(str); +#else + if ((id == TRACE_ID_WARN) || (id == TRACE_ID_PANIC) || + (id == TRACE_ID_ASSERT_FAILED) || +#if defined(INTERFACE_TESTS) + (id == TRACE_ID_TEST) || +#endif + (id == TRACE_ID_DEBUG)) { + soc_qemu_console_puts(str); + } +#endif +} + +void +soc_qemu_uart_init(void) +{ + virt_range_result_t range = hyp_aspace_allocate(PLATFORM_UART_SIZE); + if (range.e != OK) { + panic("uart: Address allocation failed."); + } + + pgtable_hyp_start(); + + // Map UART + uart = (soc_qemu_uart_t *)range.r.base; + error_t ret = pgtable_hyp_map(partition_get_private(), (uintptr_t)uart, + PLATFORM_UART_SIZE, PLATFORM_UART_BASE, + PGTABLE_HYP_MEMTYPE_NOSPEC_NOCOMBINE, + PGTABLE_ACCESS_RW, + VMSA_SHAREABILITY_NON_SHAREABLE); + if (ret != OK) { + panic("uart: Mapping failed."); + } + + pgtable_hyp_commit(); +}