aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arc
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2015-12-11 07:34:22 -0500
committerVineet Gupta <vgupta@synopsys.com>2015-12-17 00:40:23 -0500
commitbc79c9a7216562a2035d2f64f73626613c1300d0 (patch)
tree7dceeabe3e3ec851813eb6f752e15eeb95bc7f58 /arch/arc
parentff1c0b6a795bce744527bc10c8268127ed818b42 (diff)
ARC: dw2 unwind: Reinstante unwinding out of modules
The fix which removed linear searching of dwarf (because binary lookup data always exists) missed out on the fact that modules don't get the binary lookup tables info. This caused unwinding out of modules to stop working. So add binary lookup header setup (equivalent of eh_frame_hdr setup) to modules as well. While at it, confine the header setup to within unwinder code, reducing one API exposed out of unwinder code. Fixes: 2e22502c080f ARC: dw2 unwind: Remove falllback linear search thru FDE entries Cc: <stable@vger.kernel.org> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc')
-rw-r--r--arch/arc/include/asm/unwind.h4
-rw-r--r--arch/arc/kernel/setup.c1
-rw-r--r--arch/arc/kernel/unwind.c40
3 files changed, 26 insertions, 19 deletions
diff --git a/arch/arc/include/asm/unwind.h b/arch/arc/include/asm/unwind.h
index 7ca628b6ee2a..c11a25bb8158 100644
--- a/arch/arc/include/asm/unwind.h
+++ b/arch/arc/include/asm/unwind.h
@@ -112,7 +112,6 @@ struct unwind_frame_info {
112 112
113extern int arc_unwind(struct unwind_frame_info *frame); 113extern int arc_unwind(struct unwind_frame_info *frame);
114extern void arc_unwind_init(void); 114extern void arc_unwind_init(void);
115extern void arc_unwind_setup(void);
116extern void *unwind_add_table(struct module *module, const void *table_start, 115extern void *unwind_add_table(struct module *module, const void *table_start,
117 unsigned long table_size); 116 unsigned long table_size);
118extern void unwind_remove_table(void *handle, int init_only); 117extern void unwind_remove_table(void *handle, int init_only);
@@ -152,9 +151,6 @@ static inline void arc_unwind_init(void)
152{ 151{
153} 152}
154 153
155static inline void arc_unwind_setup(void)
156{
157}
158#define unwind_add_table(a, b, c) 154#define unwind_add_table(a, b, c)
159#define unwind_remove_table(a, b) 155#define unwind_remove_table(a, b)
160 156
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index c33e77c0ad3e..e1b87444ea9a 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -429,7 +429,6 @@ void __init setup_arch(char **cmdline_p)
429#endif 429#endif
430 430
431 arc_unwind_init(); 431 arc_unwind_init();
432 arc_unwind_setup();
433} 432}
434 433
435static int __init customize_machine(void) 434static int __init customize_machine(void)
diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c
index 7352475451f6..9f9ecc15556e 100644
--- a/arch/arc/kernel/unwind.c
+++ b/arch/arc/kernel/unwind.c
@@ -170,6 +170,23 @@ static struct unwind_table *find_table(unsigned long pc)
170 170
171static unsigned long read_pointer(const u8 **pLoc, 171static unsigned long read_pointer(const u8 **pLoc,
172 const void *end, signed ptrType); 172 const void *end, signed ptrType);
173static void init_unwind_hdr(struct unwind_table *table,
174 void *(*alloc) (unsigned long));
175
176/*
177 * wrappers for header alloc (vs. calling one vs. other at call site)
178 * to elide section mismatches warnings
179 */
180static void *__init unw_hdr_alloc_early(unsigned long sz)
181{
182 return __alloc_bootmem_nopanic(sz, sizeof(unsigned int),
183 MAX_DMA_ADDRESS);
184}
185
186static void *unw_hdr_alloc(unsigned long sz)
187{
188 return kmalloc(sz, GFP_KERNEL);
189}
173 190
174static void init_unwind_table(struct unwind_table *table, const char *name, 191static void init_unwind_table(struct unwind_table *table, const char *name,
175 const void *core_start, unsigned long core_size, 192 const void *core_start, unsigned long core_size,
@@ -209,6 +226,8 @@ void __init arc_unwind_init(void)
209 __start_unwind, __end_unwind - __start_unwind, 226 __start_unwind, __end_unwind - __start_unwind,
210 NULL, 0); 227 NULL, 0);
211 /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/ 228 /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
229
230 init_unwind_hdr(&root_table, unw_hdr_alloc_early);
212} 231}
213 232
214static const u32 bad_cie, not_fde; 233static const u32 bad_cie, not_fde;
@@ -241,8 +260,8 @@ static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
241 e2->fde = v; 260 e2->fde = v;
242} 261}
243 262
244static void __init setup_unwind_table(struct unwind_table *table, 263static void init_unwind_hdr(struct unwind_table *table,
245 void *(*alloc) (unsigned long)) 264 void *(*alloc) (unsigned long))
246{ 265{
247 const u8 *ptr; 266 const u8 *ptr;
248 unsigned long tableSize = table->size, hdrSize; 267 unsigned long tableSize = table->size, hdrSize;
@@ -300,9 +319,11 @@ static void __init setup_unwind_table(struct unwind_table *table,
300 319
301 hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int) 320 hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
302 + 2 * n * sizeof(unsigned long); 321 + 2 * n * sizeof(unsigned long);
322
303 header = alloc(hdrSize); 323 header = alloc(hdrSize);
304 if (!header) 324 if (!header)
305 return; 325 return;
326
306 header->version = 1; 327 header->version = 1;
307 header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native; 328 header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
308 header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4; 329 header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
@@ -342,18 +363,6 @@ static void __init setup_unwind_table(struct unwind_table *table,
342 table->header = (const void *)header; 363 table->header = (const void *)header;
343} 364}
344 365
345static void *__init balloc(unsigned long sz)
346{
347 return __alloc_bootmem_nopanic(sz,
348 sizeof(unsigned int),
349 __pa(MAX_DMA_ADDRESS));
350}
351
352void __init arc_unwind_setup(void)
353{
354 setup_unwind_table(&root_table, balloc);
355}
356
357#ifdef CONFIG_MODULES 366#ifdef CONFIG_MODULES
358 367
359static struct unwind_table *last_table; 368static struct unwind_table *last_table;
@@ -377,6 +386,8 @@ void *unwind_add_table(struct module *module, const void *table_start,
377 table_start, table_size, 386 table_start, table_size,
378 NULL, 0); 387 NULL, 0);
379 388
389 init_unwind_hdr(table, unw_hdr_alloc);
390
380#ifdef UNWIND_DEBUG 391#ifdef UNWIND_DEBUG
381 unw_debug("Table added for [%s] %lx %lx\n", 392 unw_debug("Table added for [%s] %lx %lx\n",
382 module->name, table->core.pc, table->core.range); 393 module->name, table->core.pc, table->core.range);
@@ -439,6 +450,7 @@ void unwind_remove_table(void *handle, int init_only)
439 info.init_only = init_only; 450 info.init_only = init_only;
440 451
441 unlink_table(&info); /* XXX: SMP */ 452 unlink_table(&info); /* XXX: SMP */
453 kfree(table->header);
442 kfree(table); 454 kfree(table);
443} 455}
444 456