[riscv] Support mapping early UARTs outside of the identity map

Some platforms (such as the Sipeed Lichee Pi 4A) choose to make early
debugging entertainingly cumbersome for the programmer.  These
platforms not only fail to provide a functional SBI debug console, but
also choose to place the UART at a physical address that cannot be
identity-mapped under the only paging model supported by the CPU.

Support such platforms by creating a virtual address mapping for the
early UART (in the 2MB megapage immediately below iPXE itself), and
using this as the UART base address whenever paging is enabled.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2025-05-27 16:18:17 +01:00
parent 98fdfdd255
commit 2e27d772ca

View File

@@ -149,10 +149,33 @@ prefix_virt:
#define print_char_uart _C2 ( print_char_uart_, EARLY_UART_MODEL ) #define print_char_uart _C2 ( print_char_uart_, EARLY_UART_MODEL )
#define early_uart_reg_base _C2 ( early_uart_reg_base_, __riscv_xlen )
/* Print character via nonexistent UART */ /* Print character via nonexistent UART */
.macro print_char_uart_none .macro print_char_uart_none
.endm .endm
/*
* Get UART base address (64-bit addressing)
*/
.macro early_uart_reg_base_64 reg
csrr \reg, satp
beqz \reg, early_uart_reg_base_64_nonpaged_\@
LOADN \reg, early_uart_reg_base_64_virt
j early_uart_reg_base_64_done_\@
early_uart_reg_base_64_nonpaged_\@:
li \reg, EARLY_UART_REG_BASE
early_uart_reg_base_64_done_\@:
.endm
/*
* Get UART base address (32-bit addressing)
*/
.macro early_uart_reg_base_32 reg
li \reg, EARLY_UART_REG_BASE
sub \reg, \reg, tp
.endm
/***************************************************************************** /*****************************************************************************
* *
* Print character via 8250-compatible early UART * Print character via 8250-compatible early UART
@@ -179,7 +202,7 @@ prefix_virt:
#define EARLY_UART_8250_LSR_THRE 0x20 #define EARLY_UART_8250_LSR_THRE 0x20
.macro print_char_uart_8250 .macro print_char_uart_8250
li a7, EARLY_UART_REG_BASE early_uart_reg_base a7
sb a0, EARLY_UART_8250_TX(a7) sb a0, EARLY_UART_8250_TX(a7)
uart_wait_\@: uart_wait_\@:
lbu a1, EARLY_UART_8250_LSR(a7) lbu a1, EARLY_UART_8250_LSR(a7)
@@ -749,6 +772,7 @@ enable_paging_64:
* a4 - PTE stride * a4 - PTE stride
* a5 - size of accessible physical address space * a5 - size of accessible physical address space
*/ */
progress " paging:" progress " paging:"
li a1, SATP_MODE_SV57 li a1, SATP_MODE_SV57
@@ -818,6 +842,14 @@ enable_paging_64_loop:
li a4, 1 li a4, 1
slli a4, a4, PTE_PPN1_LSB slli a4, a4, PTE_PPN1_LSB
/* Construct PTE[x-1] for early UART, if applicable */
#ifdef EARLY_UART_REG_BASE
li t0, ( EARLY_UART_REG_BASE & ~( ( 1 << VPN1_LSB ) - 1 ) )
srli t0, t0, PTE_PPN_SHIFT
ori t0, t0, PTE_LEAF
STOREN t0, -PTE_SIZE(a3)
#endif
/* Construct PTE[x-y] for iPXE virtual address map */ /* Construct PTE[x-y] for iPXE virtual address map */
la t0, _prefix la t0, _prefix
srli t0, t0, PTE_PPN_SHIFT srli t0, t0, PTE_PPN_SHIFT
@@ -862,6 +894,20 @@ enable_paging_64_loop:
.endif .endif
.endm .endm
/* Early UART base address when 64-bit paging is enabled
*
* When an early UART is in use, we choose to use the 2MB
* "megapage" immediately below iPXE itself to map the UART.
*/
#ifdef EARLY_UART_REG_BASE
.section ".rodata.early_uart_reg_base_64_virt", "a", @progbits
.balign 8
early_uart_reg_base_64_virt:
.dword ( _base - ( 1 << VPN1_LSB ) + \
( EARLY_UART_REG_BASE & ( ( 1 << VPN1_LSB ) - 1 ) ) )
.size early_uart_reg_base_64_virt, . - early_uart_reg_base_64_virt
#endif
/***************************************************************************** /*****************************************************************************
* *
* Disable 64-bit paging * Disable 64-bit paging
@@ -1152,6 +1198,7 @@ install:
* s6 - relocation offset * s6 - relocation offset
* tp - virtual address offset * tp - virtual address offset
*/ */
mv tp, zero
progress "\r\nSBI->iPXE hart:" progress "\r\nSBI->iPXE hart:"
print_hex_reg a0 print_hex_reg a0
progress " temp:" progress " temp:"
@@ -1167,9 +1214,6 @@ install:
mv s2, ra mv s2, ra
la s3, _edata la s3, _edata
/* Initialise virtual address offset */
mv tp, zero
/* Attempt to enable paging, if we have temporary page table space */ /* Attempt to enable paging, if we have temporary page table space */
mv a0, a2 mv a0, a2
beqz a2, 1f beqz a2, 1f