From 00377a5b8f9e574db32fa60f7544e091b3ea198f Mon Sep 17 00:00:00 2001 From: Jianyong Wu Date: Sat, 26 Feb 2022 22:27:36 +0800 Subject: [PATCH] Debug: enable kernel boot up time measurement To measure kernel boot up time, reserved region in pl011 is used as trap MMIO region to record kernel boot timestamp. For now, we trap at 2 point: the first is nearly the first instruction of kernel start; the second is just before call the init bin for userspace. These 2 points can cover the whole kernel boot time. Signed-off-by: Jianyong Wu --- arch/arm64/kernel/head.S | 16 ++++++++++++++++ drivers/tty/serial/amba-pl011.c | 5 +++++ include/linux/amba/serial.h | 11 +++++++++++ init/main.c | 5 +++++ 4 files changed, 37 insertions(+) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 17962452e31de6..3ac321006ab801 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -89,6 +89,7 @@ * x24 __primary_switch() .. relocate_kernel() current RELR displacement */ SYM_CODE_START(primary_entry) + bl trap_to_vmm bl preserve_boot_args bl init_kernel_el // w0=cpu_boot_mode adrp x23, __PHYS_OFFSET @@ -105,6 +106,21 @@ SYM_CODE_START(primary_entry) b __primary_switch SYM_CODE_END(primary_entry) +/* + * By writing to mmio region, trap to vmm to print timestamp, + * but corrupt x7 and x8. + * 0x9000f00 is debug region of pl011 + * 0x40 is the code specified in cloud hypervisor indicating the first debug + * point of kernel. + */ +SYM_CODE_START(trap_to_vmm) + movz x7, 0x0900, lsl 16 + add x7, x7, 0xf00 + mov x8, 0x40 + str w8, [x7] + ret +SYM_CODE_END(trap_to_vmm) + /* * Preserve the arguments passed by the bootloader in x0 .. x3 */ diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 52518a606c06a2..3f44e029b07d55 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -44,6 +44,8 @@ #include "amba-pl011.h" +char __iomem *pl011_debug_addr; + #define UART_NR 14 #define SERIAL_AMBA_MAJOR 204 @@ -2752,6 +2754,9 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, if (IS_ERR(base)) return PTR_ERR(base); + pl011_debug_addr = (char __iomem *)base; + pl011_debug_addr += UART011_IO_DEBUG; + index = pl011_probe_dt_alias(index, dev); uap->old_cr = 0; diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h index a1307b58cc2c6d..b2c74c7ca450de 100644 --- a/include/linux/amba/serial.h +++ b/include/linux/amba/serial.h @@ -206,6 +206,8 @@ #define UART01x_RSR_ANY (UART01x_RSR_OE|UART01x_RSR_BE|UART01x_RSR_PE|UART01x_RSR_FE) #define UART01x_FR_MODEM_ANY (UART01x_FR_DCD|UART01x_FR_DSR|UART01x_FR_CTS) +#define UART011_IO_DEBUG 0xf00 /* used for debug I/O port emulation in VM */ + #ifndef __ASSEMBLY__ struct amba_device; /* in uncompress this is included but amba/bus.h is not */ struct amba_pl010_data { @@ -225,4 +227,13 @@ struct amba_pl011_data { }; #endif +extern char __iomem *pl011_debug_addr; /* save the pl011 debug mmio address, equal to base + UART011_IO_DEBUG */ +#define DEBUG_TRAP_VAL_END_BOOT 0x41 /* debug point at the end of kernel boot */ + +/* wrapper of tricking pl011 debug */ +static inline void pl011_debug_trap(char val) +{ + writeb_relaxed(val, pl011_debug_addr); +} + #endif diff --git a/init/main.c b/init/main.c index 1f4a209cad6a6d..2f8f4e0687ae4e 100644 --- a/init/main.c +++ b/init/main.c @@ -100,6 +100,7 @@ #include #include #include +#include #include #include @@ -1536,6 +1537,10 @@ static int __ref kernel_init(void *unused) outb(0x41, 0x80); #endif +#ifdef CONFIG_ARM64 + pl011_debug_trap(DEBUG_TRAP_VAL_END_BOOT); +#endif + if (ramdisk_execute_command) { ret = run_init_process(ramdisk_execute_command); if (!ret)