1bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas/* 2bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * arch/arm/kernel/unwind.c 3bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * 4bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * Copyright (C) 2008 ARM Limited 5bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * 6bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * This program is free software; you can redistribute it and/or modify 7bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * it under the terms of the GNU General Public License version 2 as 8bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * published by the Free Software Foundation. 9bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * 10bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * This program is distributed in the hope that it will be useful, 11bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * but WITHOUT ANY WARRANTY; without even the implied warranty of 12bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * GNU General Public License for more details. 14bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * 15bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * You should have received a copy of the GNU General Public License 16bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * along with this program; if not, write to the Free Software 17bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * 19bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * 20bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * Stack unwinding support for ARM 21bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * 22bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * An ARM EABI version of gcc is required to generate the unwind 23bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * tables. For information about the structure of the unwind tables, 24bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * see "Exception Handling ABI for the ARM Architecture" at: 25bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * 26bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * http://infocenter.arm.com/help/topic/com.arm.doc.subset.swdev.abi/index.html 27bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas */ 28bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 29830703c766ed49bc740321df55a11d19154f95d5Alexander Shishkin#ifndef __CHECKER__ 306603a4fd5195a004dec5f9568e38ff76bae630c1Claudio Scordino#if !defined (__ARM_EABI__) 316603a4fd5195a004dec5f9568e38ff76bae630c1Claudio Scordino#warning Your compiler does not have EABI support. 326603a4fd5195a004dec5f9568e38ff76bae630c1Claudio Scordino#warning ARM unwind is known to compile only with EABI compilers. 336603a4fd5195a004dec5f9568e38ff76bae630c1Claudio Scordino#warning Change compiler or disable ARM_UNWIND option. 346603a4fd5195a004dec5f9568e38ff76bae630c1Claudio Scordino#elif (__GNUC__ == 4 && __GNUC_MINOR__ <= 2) 356603a4fd5195a004dec5f9568e38ff76bae630c1Claudio Scordino#warning Your compiler is too buggy; it is known to not compile ARM unwind support. 366603a4fd5195a004dec5f9568e38ff76bae630c1Claudio Scordino#warning Change compiler or disable ARM_UNWIND option. 376603a4fd5195a004dec5f9568e38ff76bae630c1Claudio Scordino#endif 38830703c766ed49bc740321df55a11d19154f95d5Alexander Shishkin#endif /* __CHECKER__ */ 396603a4fd5195a004dec5f9568e38ff76bae630c1Claudio Scordino 40bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas#include <linux/kernel.h> 41bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas#include <linux/init.h> 42ecea4ab6d3d8bb4122522398200f1cd2a06af6d5Paul Gortmaker#include <linux/export.h> 43bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas#include <linux/sched.h> 44bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas#include <linux/slab.h> 45bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas#include <linux/spinlock.h> 46bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas#include <linux/list.h> 47bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 48bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas#include <asm/stacktrace.h> 49bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas#include <asm/traps.h> 50bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas#include <asm/unwind.h> 51bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 52bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas/* Dummy functions to avoid linker complaints */ 53bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasvoid __aeabi_unwind_cpp_pr0(void) 54bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas{ 55bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas}; 56bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin MarinasEXPORT_SYMBOL(__aeabi_unwind_cpp_pr0); 57bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 58bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasvoid __aeabi_unwind_cpp_pr1(void) 59bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas{ 60bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas}; 61bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin MarinasEXPORT_SYMBOL(__aeabi_unwind_cpp_pr1); 62bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 63bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasvoid __aeabi_unwind_cpp_pr2(void) 64bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas{ 65bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas}; 66bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin MarinasEXPORT_SYMBOL(__aeabi_unwind_cpp_pr2); 67bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 68bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasstruct unwind_ctrl_block { 69bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long vrs[16]; /* virtual register set */ 70de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König const unsigned long *insn; /* pointer to the current instructions word */ 71bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas int entries; /* number of entries left to interpret */ 72bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas int byte; /* current byte number in the instructions word */ 73bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas}; 74bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 75bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasenum regs { 76b86040a59feb255a8193173caa4d5199464433d5Catalin Marinas#ifdef CONFIG_THUMB2_KERNEL 77b86040a59feb255a8193173caa4d5199464433d5Catalin Marinas FP = 7, 78b86040a59feb255a8193173caa4d5199464433d5Catalin Marinas#else 79bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas FP = 11, 80b86040a59feb255a8193173caa4d5199464433d5Catalin Marinas#endif 81bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas SP = 13, 82bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas LR = 14, 83bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas PC = 15 84bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas}; 85bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 86de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-Königextern const struct unwind_idx __start_unwind_idx[]; 87de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-Königstatic const struct unwind_idx *__origin_unwind_idx; 88de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-Königextern const struct unwind_idx __stop_unwind_idx[]; 89bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 90bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasstatic DEFINE_SPINLOCK(unwind_lock); 91bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasstatic LIST_HEAD(unwind_tables); 92bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 93bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas/* Convert a prel31 symbol to an absolute address */ 94bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas#define prel31_to_addr(ptr) \ 95bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas({ \ 96bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* sign-extend to 32 bits */ \ 97bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas long offset = (((long)*(ptr)) << 1) >> 1; \ 98bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas (unsigned long)(ptr) + offset; \ 99bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas}) 100bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 101bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas/* 102de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König * Binary search in the unwind index. The entries are 103bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * guaranteed to be sorted in ascending order by the linker. 104de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König * 105de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König * start = first entry 106de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König * origin = first entry with positive offset (or stop if there is no such entry) 107de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König * stop - 1 = last entry 108bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas */ 109de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-Königstatic const struct unwind_idx *search_index(unsigned long addr, 110de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König const struct unwind_idx *start, 111de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König const struct unwind_idx *origin, 112de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König const struct unwind_idx *stop) 113bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas{ 114de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König unsigned long addr_prel31; 115de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König 116de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König pr_debug("%s(%08lx, %p, %p, %p)\n", 117de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König __func__, addr, start, origin, stop); 118de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König 119de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König /* 120de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König * only search in the section with the matching sign. This way the 121de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König * prel31 numbers can be compared as unsigned longs. 122de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König */ 123de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König if (addr < (unsigned long)start) 124de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König /* negative offsets: [start; origin) */ 125de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König stop = origin; 126de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König else 127de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König /* positive offsets: [origin; stop) */ 128de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König start = origin; 129de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König 130de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König /* prel31 for address relavive to start */ 131de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König addr_prel31 = (addr - (unsigned long)start) & 0x7fffffff; 132bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 133de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König while (start < stop - 1) { 134de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König const struct unwind_idx *mid = start + ((stop - start) >> 1); 135de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König 136de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König /* 137de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König * As addr_prel31 is relative to start an offset is needed to 138de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König * make it relative to mid. 139de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König */ 140de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König if (addr_prel31 - ((unsigned long)mid - (unsigned long)start) < 141de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König mid->addr_offset) 142de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König stop = mid; 143de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König else { 144de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König /* keep addr_prel31 relative to start */ 145de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König addr_prel31 -= ((unsigned long)mid - 146de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König (unsigned long)start); 147de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König start = mid; 148de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König } 149de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König } 150de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König 151de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König if (likely(start->addr_offset <= addr_prel31)) 152de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König return start; 153de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König else { 154bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_warning("unwind: Unknown symbol address %08lx\n", addr); 155bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return NULL; 156de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König } 157de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König} 158bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 159de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-Königstatic const struct unwind_idx *unwind_find_origin( 160de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König const struct unwind_idx *start, const struct unwind_idx *stop) 161de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König{ 162de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König pr_debug("%s(%p, %p)\n", __func__, start, stop); 163ddf5a25c5fdd4cc276edf451871c38002eec0f95Uwe Kleine-König while (start < stop) { 164de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König const struct unwind_idx *mid = start + ((stop - start) >> 1); 165bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 166de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König if (mid->addr_offset >= 0x40000000) 167de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König /* negative offset */ 168ddf5a25c5fdd4cc276edf451871c38002eec0f95Uwe Kleine-König start = mid + 1; 169bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas else 170de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König /* positive offset */ 171de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König stop = mid; 172bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 173de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König pr_debug("%s -> %p\n", __func__, stop); 174de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König return stop; 175bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas} 176bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 177de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-Königstatic const struct unwind_idx *unwind_find_idx(unsigned long addr) 178bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas{ 179de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König const struct unwind_idx *idx = NULL; 180bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long flags; 181bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 182bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_debug("%s(%08lx)\n", __func__, addr); 183bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 184de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König if (core_kernel_text(addr)) { 185de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König if (unlikely(!__origin_unwind_idx)) 186de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König __origin_unwind_idx = 187de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König unwind_find_origin(__start_unwind_idx, 188de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König __stop_unwind_idx); 189de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König 190bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* main unwind table */ 191bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas idx = search_index(addr, __start_unwind_idx, 192de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König __origin_unwind_idx, 193de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König __stop_unwind_idx); 194de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König } else { 195bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* module unwind tables */ 196bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas struct unwind_table *table; 197bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 198bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas spin_lock_irqsave(&unwind_lock, flags); 199bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas list_for_each_entry(table, &unwind_tables, list) { 200bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (addr >= table->begin_addr && 201bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas addr < table->end_addr) { 202bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas idx = search_index(addr, table->start, 203de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König table->origin, 204de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König table->stop); 2055333a3de3cdd739ec4f6d501f5f6d09bab7ff919Phil Carmody /* Move-to-front to exploit common traces */ 2065333a3de3cdd739ec4f6d501f5f6d09bab7ff919Phil Carmody list_move(&table->list, &unwind_tables); 207bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas break; 208bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 209bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 210bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas spin_unlock_irqrestore(&unwind_lock, flags); 211bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 212bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 213bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_debug("%s: idx = %p\n", __func__, idx); 214bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return idx; 215bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas} 216bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 217bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasstatic unsigned long unwind_get_byte(struct unwind_ctrl_block *ctrl) 218bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas{ 219bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long ret; 220bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 221bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (ctrl->entries <= 0) { 222bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_warning("unwind: Corrupt unwind table\n"); 223bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return 0; 224bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 225bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 226bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ret = (*ctrl->insn >> (ctrl->byte * 8)) & 0xff; 227bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 228bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (ctrl->byte == 0) { 229bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->insn++; 230bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->entries--; 231bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->byte = 3; 232bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } else 233bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->byte--; 234bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 235bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return ret; 236bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas} 237bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 238bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas/* 239bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * Execute the current unwind instruction. 240bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas */ 241bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasstatic int unwind_exec_insn(struct unwind_ctrl_block *ctrl) 242bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas{ 243bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long insn = unwind_get_byte(ctrl); 244bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 245bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_debug("%s: insn = %08lx\n", __func__, insn); 246bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 247bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if ((insn & 0xc0) == 0x00) 248bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[SP] += ((insn & 0x3f) << 2) + 4; 249bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas else if ((insn & 0xc0) == 0x40) 250bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[SP] -= ((insn & 0x3f) << 2) + 4; 251bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas else if ((insn & 0xf0) == 0x80) { 252bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long mask; 253bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; 254bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas int load_sp, reg = 4; 255bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 256bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas insn = (insn << 8) | unwind_get_byte(ctrl); 257bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas mask = insn & 0x0fff; 258bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (mask == 0) { 259bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_warning("unwind: 'Refuse to unwind' instruction %04lx\n", 260bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas insn); 261bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return -URC_FAILURE; 262bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 263bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 264bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* pop R4-R15 according to mask */ 265bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas load_sp = mask & (1 << (13 - 4)); 266bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas while (mask) { 267bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (mask & 1) 268bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[reg] = *vsp++; 269bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas mask >>= 1; 270bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas reg++; 271bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 272bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (!load_sp) 273bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[SP] = (unsigned long)vsp; 274bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } else if ((insn & 0xf0) == 0x90 && 275bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas (insn & 0x0d) != 0x0d) 276bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[SP] = ctrl->vrs[insn & 0x0f]; 277bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas else if ((insn & 0xf0) == 0xa0) { 278bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; 279bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas int reg; 280bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 281bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* pop R4-R[4+bbb] */ 282bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas for (reg = 4; reg <= 4 + (insn & 7); reg++) 283bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[reg] = *vsp++; 284bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (insn & 0x80) 285bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[14] = *vsp++; 286bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[SP] = (unsigned long)vsp; 287bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } else if (insn == 0xb0) { 288c894ed6956f126d60d888e8efc5fb3a595ba89aeCatalin Marinas if (ctrl->vrs[PC] == 0) 289c894ed6956f126d60d888e8efc5fb3a595ba89aeCatalin Marinas ctrl->vrs[PC] = ctrl->vrs[LR]; 290bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* no further processing */ 291bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->entries = 0; 292bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } else if (insn == 0xb1) { 293bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long mask = unwind_get_byte(ctrl); 294bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long *vsp = (unsigned long *)ctrl->vrs[SP]; 295bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas int reg = 0; 296bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 297bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (mask == 0 || mask & 0xf0) { 298bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_warning("unwind: Spare encoding %04lx\n", 299bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas (insn << 8) | mask); 300bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return -URC_FAILURE; 301bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 302bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 303bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* pop R0-R3 according to mask */ 304bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas while (mask) { 305bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (mask & 1) 306bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[reg] = *vsp++; 307bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas mask >>= 1; 308bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas reg++; 309bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 310bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[SP] = (unsigned long)vsp; 311bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } else if (insn == 0xb2) { 312bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long uleb128 = unwind_get_byte(ctrl); 313bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 314bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[SP] += 0x204 + (uleb128 << 2); 315bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } else { 316bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_warning("unwind: Unhandled instruction %02lx\n", insn); 317bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return -URC_FAILURE; 318bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 319bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 320bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_debug("%s: fp = %08lx sp = %08lx lr = %08lx pc = %08lx\n", __func__, 321bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl->vrs[FP], ctrl->vrs[SP], ctrl->vrs[LR], ctrl->vrs[PC]); 322bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 323bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return URC_OK; 324bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas} 325bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 326bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas/* 327bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * Unwind a single frame starting with *sp for the symbol at *pc. It 328bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * updates the *pc and *sp with the new values. 329bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas */ 330bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasint unwind_frame(struct stackframe *frame) 331bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas{ 332bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long high, low; 333de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König const struct unwind_idx *idx; 334bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas struct unwind_ctrl_block ctrl; 335bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 336bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* only go to a higher address on the stack */ 337bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas low = frame->sp; 338d33aadbf8e9ba0b844c2a4a03723969c913ab03aWill Deacon high = ALIGN(low, THREAD_SIZE); 339bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 340bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_debug("%s(pc = %08lx lr = %08lx sp = %08lx)\n", __func__, 341bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame->pc, frame->lr, frame->sp); 342bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 343bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (!kernel_text_address(frame->pc)) 344bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return -URC_FAILURE; 345bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 346bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas idx = unwind_find_idx(frame->pc); 347bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (!idx) { 348bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_warning("unwind: Index not found %08lx\n", frame->pc); 349bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return -URC_FAILURE; 350bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 351bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 352bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl.vrs[FP] = frame->fp; 353bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl.vrs[SP] = frame->sp; 354bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl.vrs[LR] = frame->lr; 355bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl.vrs[PC] = 0; 356bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 357bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (idx->insn == 1) 358bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* can't unwind */ 359bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return -URC_FAILURE; 360bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas else if ((idx->insn & 0x80000000) == 0) 361bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* prel31 to the unwind table */ 362bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl.insn = (unsigned long *)prel31_to_addr(&idx->insn); 363bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas else if ((idx->insn & 0xff000000) == 0x80000000) 364bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* only personality routine 0 supported in the index */ 365bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl.insn = &idx->insn; 366bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas else { 367bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_warning("unwind: Unsupported personality routine %08lx in the index at %p\n", 368bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas idx->insn, idx); 369bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return -URC_FAILURE; 370bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 371bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 372bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* check the personality routine */ 373bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if ((*ctrl.insn & 0xff000000) == 0x80000000) { 374bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl.byte = 2; 375bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl.entries = 1; 376bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } else if ((*ctrl.insn & 0xff000000) == 0x81000000) { 377bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl.byte = 1; 378bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl.entries = 1 + ((*ctrl.insn & 0x00ff0000) >> 16); 379bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } else { 380bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_warning("unwind: Unsupported personality routine %08lx at %p\n", 381bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas *ctrl.insn, ctrl.insn); 382bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return -URC_FAILURE; 383bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 384bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 385bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas while (ctrl.entries > 0) { 386c894ed6956f126d60d888e8efc5fb3a595ba89aeCatalin Marinas int urc = unwind_exec_insn(&ctrl); 387bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (urc < 0) 388bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return urc; 389c894ed6956f126d60d888e8efc5fb3a595ba89aeCatalin Marinas if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= high) 390c894ed6956f126d60d888e8efc5fb3a595ba89aeCatalin Marinas return -URC_FAILURE; 391bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 392bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 393bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (ctrl.vrs[PC] == 0) 394bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas ctrl.vrs[PC] = ctrl.vrs[LR]; 395bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 396c894ed6956f126d60d888e8efc5fb3a595ba89aeCatalin Marinas /* check for infinite loop */ 397c894ed6956f126d60d888e8efc5fb3a595ba89aeCatalin Marinas if (frame->pc == ctrl.vrs[PC]) 398c894ed6956f126d60d888e8efc5fb3a595ba89aeCatalin Marinas return -URC_FAILURE; 399c894ed6956f126d60d888e8efc5fb3a595ba89aeCatalin Marinas 400bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame->fp = ctrl.vrs[FP]; 401bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame->sp = ctrl.vrs[SP]; 402bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame->lr = ctrl.vrs[LR]; 403bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame->pc = ctrl.vrs[PC]; 404bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 405bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return URC_OK; 406bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas} 407bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 408bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasvoid unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk) 409bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas{ 410bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas struct stackframe frame; 411bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas register unsigned long current_sp asm ("sp"); 412bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 413bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_debug("%s(regs = %p tsk = %p)\n", __func__, regs, tsk); 414bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 415bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (!tsk) 416bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas tsk = current; 417bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 418bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (regs) { 419bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame.fp = regs->ARM_fp; 420bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame.sp = regs->ARM_sp; 421bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame.lr = regs->ARM_lr; 42251d47999b9452a8dc7ae58a11423c5db28f21ae1Laurent Pinchart /* PC might be corrupted, use LR in that case. */ 42351d47999b9452a8dc7ae58a11423c5db28f21ae1Laurent Pinchart frame.pc = kernel_text_address(regs->ARM_pc) 42451d47999b9452a8dc7ae58a11423c5db28f21ae1Laurent Pinchart ? regs->ARM_pc : regs->ARM_lr; 425bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } else if (tsk == current) { 426bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame.fp = (unsigned long)__builtin_frame_address(0); 427bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame.sp = current_sp; 428bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame.lr = (unsigned long)__builtin_return_address(0); 429bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame.pc = (unsigned long)unwind_backtrace; 430bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } else { 431bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* task blocked in __switch_to */ 432bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame.fp = thread_saved_fp(tsk); 433bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame.sp = thread_saved_sp(tsk); 434bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas /* 435bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * The function calling __switch_to cannot be a leaf function 436bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas * so LR is recovered from the stack. 437bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas */ 438bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame.lr = 0; 439bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas frame.pc = thread_saved_pc(tsk); 440bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 441bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 442bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas while (1) { 443bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas int urc; 444bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long where = frame.pc; 445bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 446bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas urc = unwind_frame(&frame); 447bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (urc < 0) 448bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas break; 449bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas dump_backtrace_entry(where, frame.pc, frame.sp - 4); 450bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas } 451bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas} 452bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 453bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasstruct unwind_table *unwind_table_add(unsigned long start, unsigned long size, 454bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long text_addr, 455bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long text_size) 456bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas{ 457bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long flags; 458bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas struct unwind_table *tab = kmalloc(sizeof(*tab), GFP_KERNEL); 459bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 460bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas pr_debug("%s(%08lx, %08lx, %08lx, %08lx)\n", __func__, start, size, 461bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas text_addr, text_size); 462bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 463bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (!tab) 464bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return tab; 465bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 466de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König tab->start = (const struct unwind_idx *)start; 467de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König tab->stop = (const struct unwind_idx *)(start + size); 468de66a979012dbc66b1ec0125795a3f79ee667b8aUwe Kleine-König tab->origin = unwind_find_origin(tab->start, tab->stop); 469bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas tab->begin_addr = text_addr; 470bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas tab->end_addr = text_addr + text_size; 471bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 472bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas spin_lock_irqsave(&unwind_lock, flags); 473bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas list_add_tail(&tab->list, &unwind_tables); 474bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas spin_unlock_irqrestore(&unwind_lock, flags); 475bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 476bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return tab; 477bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas} 478bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 479bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinasvoid unwind_table_del(struct unwind_table *tab) 480bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas{ 481bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas unsigned long flags; 482bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 483bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas if (!tab) 484bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas return; 485bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 486bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas spin_lock_irqsave(&unwind_lock, flags); 487bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas list_del(&tab->list); 488bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas spin_unlock_irqrestore(&unwind_lock, flags); 489bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas 490bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas kfree(tab); 491bff595c15c92b9c5c8f3d32edefcef6c3cbdd59fCatalin Marinas} 492