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:
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user