1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Each architecture must implement puts() and exit() with the I/O 4 * devices exposed from QEMU, e.g. ns16550a. 5 * 6 * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@ventanamicro.com> 7 */ 8 #include <libcflat.h> 9 #include <config.h> 10 #include <asm/io.h> 11 #include <asm/spinlock.h> 12 13 /* 14 * Use this guess for the uart base in order to make an attempt at 15 * having earlier printf support. We'll overwrite it with the real 16 * base address that we read from the device tree later. This is 17 * the address we expect the virtual machine manager to put in 18 * its generated device tree. 19 */ 20 #define UART_EARLY_BASE ((u8 *)(unsigned long)CONFIG_UART_EARLY_BASE) 21 static volatile u8 *uart0_base = UART_EARLY_BASE; 22 static struct spinlock uart_lock; 23 24 void puts(const char *s) 25 { 26 spin_lock(&uart_lock); 27 while (*s) 28 writeb(*s++, uart0_base); 29 spin_unlock(&uart_lock); 30 } 31 32 /* 33 * Defining halt to take 'code' as an argument guarantees that it will 34 * be in a0 when we halt. That gives us a final chance to see the exit 35 * status while inspecting the halted unit test state. 36 */ 37 void halt(int code); 38 39 void exit(int code) 40 { 41 printf("\nEXIT: STATUS=%d\n", ((code) << 1) | 1); 42 halt(code); 43 __builtin_unreachable(); 44 } 45