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 <derrick.huang@rock-chips.com>
This commit is contained in:
XiaoDong Huang
2023-01-17 12:18:07 +08:00
parent df5631facd
commit 2f1f9472bd

View File

@ -291,13 +291,17 @@ EXPORT_SYMBOL_GPL(sip_smc_lastlog_request);
*/ */
#ifdef CONFIG_ARM64 #ifdef CONFIG_ARM64
#define SIP_UARTDBG_FN SIP_UARTDBG_CFG64 #define SIP_UARTDBG_FN SIP_UARTDBG_CFG64
#define SIP_FIQ_DBG_STACK_SIZE IRQ_STACK_SIZE
#else #else
#define SIP_UARTDBG_FN SIP_UARTDBG_CFG #define SIP_UARTDBG_FN SIP_UARTDBG_CFG
#define SIP_FIQ_DBG_STACK_SIZE SZ_8K
static int firmware_64_32bit; static int firmware_64_32bit;
#endif #endif
static int fiq_sip_enabled; static int fiq_sip_enabled;
static int fiq_target_cpu; static int fiq_target_cpu;
static unsigned long fiq_stack_top;
static phys_addr_t ft_fiq_mem_phy; static phys_addr_t ft_fiq_mem_phy;
static void __iomem *ft_fiq_mem_base; static void __iomem *ft_fiq_mem_base;
static sip_fiq_debugger_uart_irq_tf_cb_t sip_fiq_debugger_uart_irq_tf; 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; 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 */ /* init fiq debugger callback */
sip_fiq_debugger_uart_irq_tf = callback_fn; sip_fiq_debugger_uart_irq_tf = callback_fn;
res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, irq_id, arm_smccc_smc(SIP_UARTDBG_FN,
(unsigned long)sip_fiq_debugger_uart_irq_tf_cb, irq_id,
UARTDBG_CFG_INIT); (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)) { if (IS_SIP_ERROR(res.a0)) {
pr_err("%s error: %d\n", __func__, (int)res.a0); pr_err("%s error: %d\n", __func__, (int)res.a0);
return res.a0; return res.a0;