|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v1 1/1] xen/riscv: replace SBI early console with 8250 UART
As noted by the TODO, the legacy SBI console extension is planned
for deprecation. Replace it with direct access to UART MMIO.
Signed-off-by: Zhang Zheng <zhangzheng@xxxxxxxxxxx>
---
xen/arch/riscv/Kconfig.debug | 53 ++++++++++++++++++++--
xen/arch/riscv/configs/tiny64_defconfig | 2 +
xen/arch/riscv/early_printk.c | 37 +++++++---------
xen/arch/riscv/include/asm/early_printk.h | 12 +++++
xen/arch/riscv/include/asm/fixmap.h | 6 ++-
xen/arch/riscv/include/asm/sbi.h | 7 ---
xen/arch/riscv/mm.c | 41 +++++++++++++----
xen/arch/riscv/riscv64/Makefile | 1 +
xen/arch/riscv/riscv64/debug-8250.inc | 51 +++++++++++++++++++++
xen/arch/riscv/riscv64/debug.S | 54 +++++++++++++++++++++++
xen/arch/riscv/sbi.c | 5 ---
11 files changed, 223 insertions(+), 46 deletions(-)
create mode 100644 xen/arch/riscv/riscv64/debug-8250.inc
create mode 100644 xen/arch/riscv/riscv64/debug.S
diff --git a/xen/arch/riscv/Kconfig.debug b/xen/arch/riscv/Kconfig.debug
index 608c9ff832..51536e7151 100644
--- a/xen/arch/riscv/Kconfig.debug
+++ b/xen/arch/riscv/Kconfig.debug
@@ -1,5 +1,50 @@
+choice
+ bool "Early printk"
+ optional
+ help
+ You may want to enable early printk if you are debugging code
+ that executes before the console is initialized.
+
+ Note that selecting this option will limit Xen to a single UART
+ definition. Attempting to boot the Xen image on a different
+ platform will not work, so this option should not be enabled
+ for Xen images that are intended to be portable.
+
+ Choose one of the UART drivers for early printk, then specify
+ parameters such as the base address.
+
+ config EARLY_UART_CHOICE_8250
+ select EARLY_UART_8250
+ bool "Early printk via 8250 UART"
+ help
+ Say Y here if you wish early printk to direct its output
+ to an already configured 8250-compatible UART.
+
+endchoice
+
+config EARLY_UART_8250
+ select EARLY_PRINTK
+ bool
+
config EARLY_PRINTK
- bool "Enable early printk"
- default DEBUG
- help
- Enables early printk debug messages
+ bool
+
+config EARLY_UART_BASE_ADDRESS
+ depends on EARLY_UART_8250
+ hex "Early printk, physical base address of debug UART"
+
+config EARLY_UART_8250_REG_SHIFT
+ depends on EARLY_UART_8250
+ int "Early printk, left-shift to apply to the register offsets within
the 8250 UART"
+ default 0
+ range 0 4
+ help
+ EARLY_UART_8250_REG_SHIFT is, optionally, the left-shift to
+ apply to the register offsets within the UART with early
+ printk.
+
+ Default to 0.
+
+config EARLY_PRINTK_INC
+ string
+ default "debug-8250.inc" if EARLY_UART_8250
diff --git a/xen/arch/riscv/configs/tiny64_defconfig
b/xen/arch/riscv/configs/tiny64_defconfig
index 2399f7b918..438db66551 100644
--- a/xen/arch/riscv/configs/tiny64_defconfig
+++ b/xen/arch/riscv/configs/tiny64_defconfig
@@ -10,3 +10,5 @@ CONFIG_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_EXPERT=y
CONFIG_QEMU_PLATFORM=y
+CONFIG_EARLY_UART_CHOICE_8250=y
+CONFIG_EARLY_UART_BASE_ADDRESS=0x10000000
diff --git a/xen/arch/riscv/early_printk.c b/xen/arch/riscv/early_printk.c
index 634141354c..bb2dc6c719 100644
--- a/xen/arch/riscv/early_printk.c
+++ b/xen/arch/riscv/early_printk.c
@@ -1,42 +1,37 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * RISC-V early printk using SBI
+ * RISC-V early printk
*
* Copyright (C) 2021 Bobby Eshleman <bobbyeshleman@xxxxxxxxx>
*/
-#include <asm/early_printk.h>
-#include <asm/sbi.h>
+#include <xen/early_printk.h>
-/*
- * When the MMU is off during early boot, any C function called has to
- * use PC-relative rather than absolute address because the physical address
- * may not match the virtual address.
- *
- * To guarantee PC-relative address cmodel=medany should be used
- */
#ifndef __riscv_cmodel_medany
#error "early_*() can be called from head.S with MMU-off"
#endif
-/*
- * TODO:
- * sbi_console_putchar is already planned for deprecation
- * so it should be reworked to use UART directly.
-*/
+void early_putch(char c);
+void early_flush(void);
+
void early_puts(const char *s, size_t nr)
{
while ( nr-- > 0 )
{
- sbi_console_putchar(*s);
+ if ( *s == '\n' )
+ early_putch('\r');
+ early_putch(*s);
s++;
}
+
+ early_flush();
}
void early_printk(const char *str)
{
- while ( *str )
- {
- early_puts(str, 1);
- str++;
- }
+ const char *end = str;
+
+ while ( *end )
+ end++;
+
+ early_puts(str, end - str);
}
diff --git a/xen/arch/riscv/include/asm/early_printk.h
b/xen/arch/riscv/include/asm/early_printk.h
index 2750045bdd..e4c95ed7b4 100644
--- a/xen/arch/riscv/include/asm/early_printk.h
+++ b/xen/arch/riscv/include/asm/early_printk.h
@@ -3,6 +3,7 @@
#ifndef ASM__RISCV__EARLY_PRINTK_H
#define ASM__RISCV__EARLY_PRINTK_H
+#ifndef __ASSEMBLER__
#include <xen/early_printk.h>
#ifdef CONFIG_EARLY_PRINTK
@@ -10,5 +11,16 @@ void early_printk(const char *str);
#else
static inline void early_printk(const char *s) {};
#endif
+#endif
+
+#ifdef CONFIG_EARLY_PRINTK
+
+#include <xen/page-size.h>
+#include <asm/fixmap.h>
+
+/* need to add the uart address offset in page to the fixmap address */
+#define EARLY_UART_VIRTUAL_ADDRESS \
+ (FIXMAP_ADDR(FIX_CONSOLE) + (CONFIG_EARLY_UART_BASE_ADDRESS & ~PAGE_MASK))
+#endif
#endif /* ASM__RISCV__EARLY_PRINTK_H */
diff --git a/xen/arch/riscv/include/asm/fixmap.h
b/xen/arch/riscv/include/asm/fixmap.h
index 085d135c15..66a78bb19d 100644
--- a/xen/arch/riscv/include/asm/fixmap.h
+++ b/xen/arch/riscv/include/asm/fixmap.h
@@ -17,8 +17,12 @@
#define FIX_PMAP_BEGIN (0) /* Start of PMAP */
#define FIX_PMAP_END (FIX_PMAP_BEGIN + NUM_FIX_PMAP - 1) /* End of PMAP */
#define FIX_MISC (FIX_PMAP_END + 1) /* Ephemeral mappings of hardware */
-
+#ifdef CONFIG_EARLY_PRINTK
+#define FIX_CONSOLE (FIX_MISC + 1) /* Early UART mapping */
+#define FIX_LAST FIX_CONSOLE
+#else
#define FIX_LAST FIX_MISC
+#endif
#define FIXADDR_START FIXMAP_ADDR(0)
#define FIXADDR_TOP FIXMAP_ADDR(FIX_LAST + 1)
diff --git a/xen/arch/riscv/include/asm/sbi.h b/xen/arch/riscv/include/asm/sbi.h
index 1952868e96..d043fc7632 100644
--- a/xen/arch/riscv/include/asm/sbi.h
+++ b/xen/arch/riscv/include/asm/sbi.h
@@ -75,13 +75,6 @@ struct sbiret sbi_ecall(unsigned long ext, unsigned long fid,
unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);
-/**
- * Writes given character to the console device.
- *
- * @param ch The data to be written to the console.
- */
-void sbi_console_putchar(int ch);
-
void sbi_shutdown(void);
/*
diff --git a/xen/arch/riscv/mm.c b/xen/arch/riscv/mm.c
index 610d111945..8480e61de2 100644
--- a/xen/arch/riscv/mm.c
+++ b/xen/arch/riscv/mm.c
@@ -76,6 +76,27 @@ stage1_pgtbl_nonroot[PGTBL_INITIAL_COUNT *
PAGETABLE_ENTRIES];
pte_t __section(".bss.page_aligned") __aligned(PAGE_SIZE)
xen_fixmap[PAGETABLE_ENTRIES];
+#ifdef CONFIG_EARLY_PRINTK
+static void __init setup_early_uart_mapping(void)
+{
+ pte_t *pgtbl = stage1_pgtbl_root;
+ unsigned int i;
+
+ /* Add UART to the fixmap table. */
+ xen_fixmap[pt_index(0, EARLY_UART_VIRTUAL_ADDRESS)] =
+ paddr_to_pte(CONFIG_EARLY_UART_BASE_ADDRESS & PAGE_MASK,
+ PAGE_HYPERVISOR_RW);
+
+ for ( i = HYP_PT_ROOT_LEVEL; i > 1; i-- )
+ pgtbl = (pte_t *)pte_to_paddr(
+ pgtbl[pt_index(i, FIXMAP_ADDR(0))]);
+
+ /* Map fixmap into the initial page tables. */
+ pgtbl[pt_index(1, FIXMAP_ADDR(0))] =
+ paddr_to_pte((paddr_t)xen_fixmap, PTE_TABLE);
+}
+#endif
+
#define HANDLE_PGTBL(curr_lvl_num) \
index = pt_index(curr_lvl_num, page_addr); \
if ( pte_is_valid(pgtbl[index]) ) \
@@ -243,18 +264,18 @@ void __init setup_fixmap_mappings(void)
pte = &pte[pt_index(i, FIXMAP_ADDR(0))];
}
- BUG_ON(pte_is_valid(*pte));
-
- tmp = paddr_to_pte(virt_to_maddr(&xen_fixmap), PTE_TABLE);
- write_pte(pte, tmp);
+ if ( pte_is_valid(*pte) )
+ BUG_ON(pte_to_paddr(*pte) != virt_to_maddr(xen_fixmap));
+ else
+ {
+ tmp = paddr_to_pte(virt_to_maddr(xen_fixmap), PTE_TABLE);
+ write_pte(pte, tmp);
+ }
RISCV_FENCE(rw, rw);
sfence_vma();
- /*
- * We only need the zeroeth table allocated, but not the PTEs set, because
- * set_fixmap() will set them on the fly.
- */
+ /* Remaining fixmap entries are populated on demand by set_fixmap(). */
}
/*
@@ -314,6 +335,10 @@ void __init setup_initial_pagetables(void)
linker_end,
load_start);
+#ifdef CONFIG_EARLY_PRINTK
+ setup_early_uart_mapping();
+#endif
+
if ( linker_start == load_start )
return;
diff --git a/xen/arch/riscv/riscv64/Makefile b/xen/arch/riscv/riscv64/Makefile
index 3340058c08..a35968ead7 100644
--- a/xen/arch/riscv/riscv64/Makefile
+++ b/xen/arch/riscv/riscv64/Makefile
@@ -1 +1,2 @@
+obj-$(CONFIG_EARLY_PRINTK) += debug.o
obj-y += head.o
diff --git a/xen/arch/riscv/riscv64/debug-8250.inc
b/xen/arch/riscv/riscv64/debug-8250.inc
new file mode 100644
index 0000000000..5918e74cbd
--- /dev/null
+++ b/xen/arch/riscv/riscv64/debug-8250.inc
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * xen/arch/riscv/riscv64/debug-8250.inc
+ *
+ * 8250 specific debug code
+ *
+ * Copyright (c) 2013 Applied Micro.
+ * Copyright (c) 2026 Zheng Zhang.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <xen/8250-uart.h>
+
+/*
+ * UART wait UART to be ready to transmit
+ * xb: register which contains the UART base address
+ * c: scratch register
+ */
+.macro early_uart_ready xb c
+1:
+ lbu \c, (UART_LSR << CONFIG_EARLY_UART_8250_REG_SHIFT)(\xb)
+ andi \c, \c, UART_LSR_THRE
+ xori \c, \c, UART_LSR_THRE
+ bnez \c, 1b
+.endm
+
+/*
+ * UART transmit character
+ * xb: register which contains the UART base address
+ * wt: register which contains the character to transmit
+ */
+.macro early_uart_transmit xb wt
+ /* UART_THR transmit holding */
+ sb \wt, (UART_THR << CONFIG_EARLY_UART_8250_REG_SHIFT)(\xb)
+.endm
+
+/*
+ * Local variables:
+ * mode: ASM
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/riscv/riscv64/debug.S b/xen/arch/riscv/riscv64/debug.S
new file mode 100644
index 0000000000..4e7465e1d8
--- /dev/null
+++ b/xen/arch/riscv/riscv64/debug.S
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * xen/arch/riscv/riscv64/debug.S
+ *
+ * Wrapper for early printk
+ *
+ * Julien Grall <julien.grall@xxxxxxxxxx>
+ * Copyright (c) 2013 Linaro Limited.
+ * Copyright (c) 2026 Zheng Zhang.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <asm/asm.h>
+#include <asm/early_printk.h>
+#include <asm/riscv_encoding.h>
+
+#include CONFIG_EARLY_PRINTK_INC
+
+.macro early_uart_base bs, c
+ li \bs, CONFIG_EARLY_UART_BASE_ADDRESS
+ csrr \c, CSR_SATP
+ beqz \c, 1f
+ li \bs, EARLY_UART_VIRTUAL_ADDRESS
+1:
+.endm
+
+/* Print the character in a0. */
+FUNC(early_putch)
+ early_uart_base t0, t1
+ early_uart_ready t0, t1
+ andi a0, a0, 0xff
+ early_uart_transmit t0, a0
+ ret
+END(early_putch)
+
+/* Wait until both the transmit FIFO and shift register are empty. */
+FUNC(early_flush)
+ early_uart_base t0, t1
+1:
+ lbu t1, (UART_LSR << CONFIG_EARLY_UART_8250_REG_SHIFT)(t0)
+ andi t1, t1, (UART_LSR_THRE | UART_LSR_TEMT)
+ xori t1, t1, (UART_LSR_THRE | UART_LSR_TEMT)
+ bnez t1, 1b
+ ret
+END(early_flush)
diff --git a/xen/arch/riscv/sbi.c b/xen/arch/riscv/sbi.c
index 3576e26033..bca3ebdca5 100644
--- a/xen/arch/riscv/sbi.c
+++ b/xen/arch/riscv/sbi.c
@@ -72,11 +72,6 @@ static int sbi_err_map_xen_errno(int err)
};
}
-void sbi_console_putchar(int ch)
-{
- sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch, 0, 0, 0, 0, 0);
-}
-
void sbi_shutdown(void)
{
sbi_ecall(SBI_EXT_0_1_SHUTDOWN, 0, 0, 0, 0, 0, 0, 0);
--
2.54.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |