From: Michael Brown Date: Tue, 27 May 2025 15:18:17 +0000 (+0100) Subject: [riscv] Support mapping early UARTs outside of the identity map X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2e27d772cab1e2a645dc7a0038dee71523f4e653;p=thirdparty%2Fipxe.git [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 --- diff --git a/src/arch/riscv/prefix/libprefix.S b/src/arch/riscv/prefix/libprefix.S index 41d03769e..e4ca54f71 100644 --- a/src/arch/riscv/prefix/libprefix.S +++ b/src/arch/riscv/prefix/libprefix.S @@ -149,10 +149,33 @@ prefix_virt: #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 */ .macro print_char_uart_none .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 @@ -179,7 +202,7 @@ prefix_virt: #define EARLY_UART_8250_LSR_THRE 0x20 .macro print_char_uart_8250 - li a7, EARLY_UART_REG_BASE + early_uart_reg_base a7 sb a0, EARLY_UART_8250_TX(a7) uart_wait_\@: lbu a1, EARLY_UART_8250_LSR(a7) @@ -749,6 +772,7 @@ enable_paging_64: * a4 - PTE stride * a5 - size of accessible physical address space */ + progress " paging:" li a1, SATP_MODE_SV57 @@ -818,6 +842,14 @@ enable_paging_64_loop: li a4, 1 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 */ la t0, _prefix srli t0, t0, PTE_PPN_SHIFT @@ -862,6 +894,20 @@ enable_paging_64_loop: .endif .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 @@ -1152,6 +1198,7 @@ install: * s6 - relocation offset * tp - virtual address offset */ + mv tp, zero progress "\r\nSBI->iPXE hart:" print_hex_reg a0 progress " temp:" @@ -1167,9 +1214,6 @@ install: mv s2, ra la s3, _edata - /* Initialise virtual address offset */ - mv tp, zero - /* Attempt to enable paging, if we have temporary page table space */ mv a0, a2 beqz a2, 1f