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