From e3e9cf23bab1d41d7595eb4bd90cda323830ea08 Mon Sep 17 00:00:00 2001 From: Jiamin Ma Date: Mon, 8 Apr 2019 17:06:27 +0800 Subject: [PATCH] time: fix fail to read generic timer's counter value correctly [1/1] PD#SWPL-6837 Problem: The return value of arch_counter_get_cntvct is always abnormal when it is in irq stack. In this case, arch_counter_get_cntvct trys to access a variable in 8Bytes via a 4Bytes aligned addr- ess, which vialates the rule: The address that is accessed should be aligned to the size of the data element being accessed Solution: after switching to irq stack, force the base sp value to be 16Bytes aligned. Since the address of variable in irq stack is based on the base sp and arranged automatically, all the data accessing in irq stack will be aligned. Verify: Ampere Change-Id: I3b30a56491dd0720d1c885bfaf2ca98d1b103fdd Signed-off-by: Jiamin Ma (cherry picked from commit 043ae971bf47dcae687412d7f52a8e7818244742) --- arch/arm/kernel/unwind.c | 2 +- drivers/amlogic/memory_ext/vmap_stack.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index ef2f007d4d49..7ad8026098f8 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -544,7 +544,7 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) sp_irq = (unsigned long)irq_stack[cpu]; addr = *((unsigned long *)(sp_irq + THREAD_INFO_OFFSET - 8 - - sizeof(addr))); + sizeof(addr) - 12)); pt_regs = (struct pt_regs *)addr; frame.fp = pt_regs->ARM_fp; frame.sp = pt_regs->ARM_sp; diff --git a/drivers/amlogic/memory_ext/vmap_stack.c b/drivers/amlogic/memory_ext/vmap_stack.c index 7f81ae545616..dae386a4d855 100644 --- a/drivers/amlogic/memory_ext/vmap_stack.c +++ b/drivers/amlogic/memory_ext/vmap_stack.c @@ -163,8 +163,9 @@ unsigned long notrace irq_stack_entry(unsigned long sp) sp_irq = (unsigned long)dst - 8; /* * save start addr of the interrupted task's context + * minus an extra 12 to force base sp 16Bytes aligned */ - sp_irq = sp_irq - sizeof(sp); + sp_irq = sp_irq - sizeof(sp) - 12; *((unsigned long *)sp_irq) = sp; return sp_irq; }