Skip to content

Commit

Permalink
soc_qemu: Add UART support
Browse files Browse the repository at this point in the history
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 <quic_cvanscha@quicinc.com>
  • Loading branch information
quic-sgamiz authored and quic-cvanscha committed Oct 27, 2021
1 parent b00cc9f commit 0579fe3
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 1 deletion.
5 changes: 4 additions & 1 deletion hyp/platform/soc_qemu/build.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
6 changes: 6 additions & 0 deletions hyp/platform/soc_qemu/include/uart.h
Original file line number Diff line number Diff line change
@@ -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);
5 changes: 5 additions & 0 deletions hyp/platform/soc_qemu/soc_qemu.ev
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 7 additions & 0 deletions hyp/platform/soc_qemu/soc_qemu.tc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
};
19 changes: 19 additions & 0 deletions hyp/platform/soc_qemu/src/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
110 changes: 110 additions & 0 deletions hyp/platform/soc_qemu/src/uart.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// © 2021 Qualcomm Innovation Center, Inc. All rights reserved.
//
// SPDX-License-Identifier: BSD-3-Clause

#include <assert.h>
#include <hyptypes.h>
#include <string.h>

#include <atomic.h>
#include <hyp_aspace.h>
#include <panic.h>
#include <partition.h>
#include <pgtable.h>
#include <preempt.h>

#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();
}

0 comments on commit 0579fe3

Please sign in to comment.