[Skiboot] [PATCH] Enable Simics UART console

Ryan Grimm grimm at linux.vnet.ibm.com
Thu Feb 18 03:27:36 AEDT 2016


The UART is a simulated ns16550 with memory mapped registers.

A /simics dt node is detected and a SIMICS_QUIRK is added to chip quirks
similar to MAMBO_CALLOUTS.  It can contain an ns16550 dt node with a property
console-bar.

The LPC UART code is reused and this will work without an LPC bus in the model.

Signed-off-by: Ryan Grimm <grimm at linux.vnet.ibm.com>
---
 core/chip.c       |  4 ++++
 core/init.c       |  2 ++
 hw/lpc-uart.c     | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 include/chip.h    |  1 +
 include/console.h |  1 +
 5 files changed, 68 insertions(+), 3 deletions(-)

diff --git a/core/chip.c b/core/chip.c
index 729bccb..49d2f1f 100644
--- a/core/chip.c
+++ b/core/chip.c
@@ -76,6 +76,10 @@ void init_chips(void)
 			| QUIRK_DISABLE_NAP;
 		prlog(PR_NOTICE, "CHIP: Detected Mambo simulator\n");
 	}
+	if (dt_find_by_path(dt_root, "/simics")) {
+		proc_chip_quirks |= QUIRK_SIMICS;
+		prlog(PR_NOTICE, "CHIP: Detected Simics simulator\n");
+	}
 	if (dt_node_is_compatible(dt_root, "qemu,powernv")) {
 		proc_chip_quirks |= QUIRK_NO_CHIPTOD | QUIRK_NO_PBA;
 		prlog(PR_NOTICE, "CHIP: Detected Qemu simulator\n");
diff --git a/core/init.c b/core/init.c
index 54a5735..142cbce 100644
--- a/core/init.c
+++ b/core/init.c
@@ -631,6 +631,8 @@ void __noreturn main_cpu_entry(const void *fdt, u32 master_cpu)
 	init_chips();
 	if (chip_quirk(QUIRK_MAMBO_CALLOUTS))
 		enable_mambo_console();
+	if (chip_quirk(QUIRK_SIMICS))
+		enable_simics_console();
 	xscom_init();
 	mfsi_init();
 
diff --git a/hw/lpc-uart.c b/hw/lpc-uart.c
index bba6354..433cdff 100644
--- a/hw/lpc-uart.c
+++ b/hw/lpc-uart.c
@@ -26,6 +26,7 @@
 #include <timebase.h>
 #include <cpu.h>
 #include <chip.h>
+#include <io.h>
 
 DEFINE_LOG_ENTRY(OPAL_RC_UART_INIT, OPAL_PLATFORM_ERR_EVT, OPAL_UART,
 		 OPAL_CEC_HARDWARE, OPAL_PREDICTIVE_ERR_GENERAL,
@@ -66,6 +67,8 @@ static uint32_t uart_base;
 static bool has_irq, irq_ok, rx_full, tx_full;
 static uint8_t tx_room;
 static uint8_t cached_ier;
+static bool simics_uart;
+static void *simics_uart_base;
 
 static void uart_trace(u8 ctx, u8 cnt, u8 irq_state, u8 in_count)
 {
@@ -80,12 +83,18 @@ static void uart_trace(u8 ctx, u8 cnt, u8 irq_state, u8 in_count)
 
 static inline uint8_t uart_read(unsigned int reg)
 {
-	return lpc_inb(uart_base + reg);
+	if (simics_uart)
+		return in_8(simics_uart_base + reg);
+	else
+		return lpc_inb(uart_base + reg);
 }
 
 static inline void uart_write(unsigned int reg, uint8_t val)
 {
-	lpc_outb(val, uart_base + reg);
+	if (simics_uart)
+		out_8(simics_uart_base + reg, val);
+	else
+		lpc_outb(val, uart_base + reg);
 }
 
 static void uart_check_tx_room(void)
@@ -137,7 +146,7 @@ static size_t uart_con_write(const char *buf, size_t len)
 	size_t written = 0;
 
 	/* If LPC bus is bad, we just swallow data */
-	if (!lpc_ok())
+	if (!lpc_ok() && !simics_uart)
 		return written;
 
 	lock(&uart_lock);
@@ -547,3 +556,51 @@ void uart_init(bool use_interrupt)
 	} else
 		has_irq = false;
 }
+
+static bool simics_con_poll_read(void) {
+	uint8_t lsr = uart_read(REG_LSR);
+	return ((lsr & LSR_DR) != 0);
+}
+
+static size_t simics_con_read(char *buf, size_t len)
+{
+	size_t count = 0;
+	while (count < len) {
+		if (!simics_con_poll_read())
+			break;
+		*(buf++) = uart_read(REG_RBR);
+		count++;
+	}
+	return count;
+}
+
+static struct con_ops simics_con_driver = {
+	.poll_read = simics_con_poll_read,
+	.read = simics_con_read,
+	.write = uart_con_write,
+};
+
+void enable_simics_console() {
+	struct dt_node *n;
+
+	printf("Enabling Simics console\n");
+
+	n = dt_find_compatible_node(dt_root, NULL, "ns16550");
+	if (!n) {
+		prerror("UART: cannot find ns16550\n");
+		return;
+	}
+
+	simics_uart_base = (void *)dt_prop_get_u64(n, "console-bar");
+	simics_uart = 1;
+	has_irq = false;
+
+	if (!uart_init_hw(dt_prop_get_u32(n, "current-speed"),
+			  dt_prop_get_u32(n, "clock-frequency"))) {
+		prerror("UART: Initialization failed\n");
+		dt_add_property_strings(n, "status", "bad");
+		return;
+	}
+
+	set_console(&simics_con_driver);
+}
diff --git a/include/chip.h b/include/chip.h
index 5109e25..9e50f7a 100644
--- a/include/chip.h
+++ b/include/chip.h
@@ -99,6 +99,7 @@ enum proc_chip_quirks {
 	QUIRK_NO_PBA		= 0x00000008,
 	QUIRK_NO_OCC_IRQ       	= 0x00000010,
 	QUIRK_DISABLE_NAP	= 0x00000020,
+	QUIRK_SIMICS		= 0x00000040,
 } proc_chip_quirks;
 
 static inline bool chip_quirk(unsigned int q)
diff --git a/include/console.h b/include/console.h
index b6fc8bf..ecb18c4 100644
--- a/include/console.h
+++ b/include/console.h
@@ -67,6 +67,7 @@ extern void console_complete_flush(void);
 extern int mambo_read(void);
 extern void mambo_write(const char *buf, size_t count);
 extern void enable_mambo_console(void);
+extern void enable_simics_console(void);
 
 ssize_t console_write(bool flush_to_drivers, const void *buf, size_t count);
 
-- 
1.9.1



More information about the Skiboot mailing list