@@ -73,6 +73,11 @@ static void uart0_init(void)
}
}
+void __iomem *io_uart_early_base(void)
+{
+ return UART_EARLY_BASE;
+}
+
void io_init(void)
{
uart0_init();
@@ -7,6 +7,9 @@
#ifndef _ARM_IO_H_
#define _ARM_IO_H_
+#include <asm/io.h>
+
extern void io_init(void);
+extern void __iomem *io_uart_early_base(void);
#endif
@@ -15,6 +15,7 @@
#include <asm/pgtable.h>
#include <asm/pgtable-hwdef.h>
+#include "io.h"
#include "vmalloc.h"
#include <linux/compiler.h>
@@ -155,6 +156,8 @@ void mmu_set_range_sect(pgd_t *pgtable, uintptr_t virt_offset,
void mmu_setup_early(phys_addr_t unused0, void *unused1)
{
struct mem_region *r;
+ pgprot_t uart_prot;
+ void *uart_base;
assert(!mmu_enabled() && !page_alloc_initialized());
@@ -178,6 +181,11 @@ void mmu_setup_early(phys_addr_t unused0, void *unused1)
}
}
+ uart_base = io_uart_early_base();
+ uart_prot = __pgprot(PTE_UNCACHED | PTE_USER | PTE_UXN | PTE_PXN);
+ install_page_prot(mmu_idmap, (phys_addr_t)(unsigned long)uart_base,
+ (uintptr_t)uart_base, uart_prot);
+
asm_mmu_enable((phys_addr_t)(unsigned long)mmu_idmap);
}
The MMU is now enabled before the UART is probed, which leaves kvm-unit-tests with a window where attempting to write to the console results in an infinite data abort loop triggered by the exception handlers themselves trying to use the console. Get around this by mapping the UART early address when creating the translation tables. Note that the address remains mapped even if the devicetree address is different. Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> --- lib/arm/io.c | 5 +++++ lib/arm/io.h | 3 +++ lib/arm/mmu.c | 8 ++++++++ 3 files changed, 16 insertions(+)