From 2f1f9472bd7927b87c9b3bdd1520250b3b50ec56 Mon Sep 17 00:00:00 2001 From: XiaoDong Huang Date: Tue, 17 Jan 2023 12:18:07 +0800 Subject: [PATCH] firmware: rockchip_sip: allocate a separate stack for fiq-debugger callback SP will point to a invalid addr at some time in kernel such as checking stack overflow, and system will crash if fiq-debugger trigger at this time. To solve it, we allocate a separate stack for fiq-debugger, and point SP at the stack before return to kernel. Change-Id: I1175ba032292d072fe2e4ae828d28313646091a7 Signed-off-by: XiaoDong Huang --- drivers/firmware/rockchip_sip.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/rockchip_sip.c b/drivers/firmware/rockchip_sip.c index 88cd7e5723b2..7f2073c63f44 100644 --- a/drivers/firmware/rockchip_sip.c +++ b/drivers/firmware/rockchip_sip.c @@ -291,13 +291,17 @@ EXPORT_SYMBOL_GPL(sip_smc_lastlog_request); */ #ifdef CONFIG_ARM64 #define SIP_UARTDBG_FN SIP_UARTDBG_CFG64 +#define SIP_FIQ_DBG_STACK_SIZE IRQ_STACK_SIZE #else #define SIP_UARTDBG_FN SIP_UARTDBG_CFG +#define SIP_FIQ_DBG_STACK_SIZE SZ_8K + static int firmware_64_32bit; #endif static int fiq_sip_enabled; static int fiq_target_cpu; +static unsigned long fiq_stack_top; static phys_addr_t ft_fiq_mem_phy; static void __iomem *ft_fiq_mem_base; static sip_fiq_debugger_uart_irq_tf_cb_t sip_fiq_debugger_uart_irq_tf; @@ -406,11 +410,26 @@ int sip_fiq_debugger_uart_irq_tf_init(u32 irq_id, sip_fiq_debugger_uart_irq_tf_c { struct arm_smccc_res res; + /* Alloc a page for fiq_debugger's stack */ + if (fiq_stack_top == 0) { + fiq_stack_top = __get_free_pages(GFP_KERNEL | __GFP_ZERO, + get_order(SIP_FIQ_DBG_STACK_SIZE)); + if (fiq_stack_top) { + fiq_stack_top += SIP_FIQ_DBG_STACK_SIZE; + } else { + pr_err("%s: alloc stack failed\n", __func__); + return -ENOMEM; + } + } + /* init fiq debugger callback */ sip_fiq_debugger_uart_irq_tf = callback_fn; - res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, irq_id, - (unsigned long)sip_fiq_debugger_uart_irq_tf_cb, - UARTDBG_CFG_INIT); + arm_smccc_smc(SIP_UARTDBG_FN, + irq_id, + (unsigned long)sip_fiq_debugger_uart_irq_tf_cb, + UARTDBG_CFG_INIT, + fiq_stack_top, 0, 0, 0, &res); + if (IS_SIP_ERROR(res.a0)) { pr_err("%s error: %d\n", __func__, (int)res.a0); return res.a0;