2.4.25 sync unwind code with 2.6.3
PATCH 1/1 2.4.25 sync unwind code with 2.6.3
The unwind code in 2.4.25 has drifted away from the 2.6.3 version, including some missing bug fixes. This patch bring 2.4.25 unwind as close to 2.6.3 as possible. Changes are :-
* Move unw_table_entry from one header to another.
* Add Fenghua Yu's change to pt_regs_off. This is not really in 2.4 yet, even though the comment says it is.
* Comment and white space changes.
* Bug fix to alloc_reg_state().
* Replace struct_offset() with offsetof().
* Export unw_* symbols.
* Avoid deadlock on script->lock.
I am not happy with the kludge that avoids the deadlock on script->lock, anybody got a better solution? The kludge assumes that the first field in an ia64 rwsem is a spinlock. I have hit this unwind deadlock a couple of times during processing of asynchronous MCA events, so I want it fixed.
After this patch, the main differences between 2.4 and 2.6 are the handing of the gate page and its DSO data.
Index: 25.4/include/asm-ia64/unwind.h
include/asm-ia64/unwind.h Mon, 23 Feb 2004 12:24:35 +1100 kaos (linux-2.4/s/17_unwind.h 1.1.3.1.3.1.1.1.1.1 644) renamed from include/asm-ia64/unwind.h Tue, 16 Sep 2003 19:32:24 +1000 kaos (linux-2.4/s/17_unwind.h 1.1.3.1.3.1.1.1.1.1 644) +6 -0
@@ -93,6 +93,12 @@ struct unw_frame_info { * The official API follows below: */ +struct unw_table_entry { + u64 start_offset; + u64 end_offset; + u64 info_offset; +}; + /* * Initialize unwind support. */
Index: 25.4/arch/ia64/kernel/unwind_i.h
arch/ia64/kernel/unwind_i.h Mon, 23 Feb 2004 12:38:43 +1100 kaos (linux-2.4/r/c/33_unwind_i.h 1.1.2.1.1.2.1.1 644) renamed from arch/ia64/kernel/unwind_i.h Sun, 06 Jul 2003 14:16:24 +1000 kaos (linux-2.4/r/c/33_unwind_i.h 1.1.2.1.1.2.1.1 644) +2 -8
@@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2002 Hewlett-Packard Co + * Copyright (C) 2000, 2002-2003 Hewlett-Packard Co * David Mosberger-Tang <[email protected]> * * Kernel unwind support.
@@ -45,12 +45,6 @@ struct unw_info_block { /* personality routine and language-specific data follow behind descriptors */ }; -struct unw_table_entry { - u64 start_offset; - u64 end_offset; - u64 info_offset; -}; - struct unw_table { struct unw_table *next; /* must be first member! */ const char *name;
@@ -148,7 +142,7 @@ struct unw_insn { }; /* - * Preserved general static registers (r2-r5) give rise to two script + * Preserved general static registers (r4-r7) give rise to two script * instructions; everything else yields at most one instruction; at * the end of the script, the psp gets popped, accounting for one more * instruction.
Index: 25.4/arch/ia64/kernel/unwind.c
arch/ia64/kernel/unwind.c Mon, 23 Feb 2004 12:38:43 +1100 kaos (linux-2.4/r/c/42_unwind.c 1.1.2.1.1.2.3.1.1.1.1.3.1.1.1.2 644) renamed from arch/ia64/kernel/unwind.c Wed, 11 Feb 2004 11:17:55 +1100 kaos (linux-2.4/r/c/42_unwind.c 1.1.2.1.1.2.3.1.1.1.1.3.1.1.1.2 644) +119 -102
377 lines not on this page · raw message
Index: 25.4/arch/ia64/kernel/Makefile
arch/ia64/kernel/Makefile Mon, 23 Feb 2004 11:45:55 +1100 kaos (linux-2.4/s/c/19_Makefile 1.1.3.1.3.1.2.1.1.2.1.1 644) renamed from arch/ia64/kernel/Makefile Tue, 16 Sep 2003 19:32:24 +1000 kaos (linux-2.4/s/c/19_Makefile 1.1.3.1.3.1.2.1.1.2.1.1 644) +1 -1
@@ -11,7 +11,7 @@ all: kernel.o head.o init_task.o O_TARGET := kernel.o -export-objs := ia64_ksyms.o +export-objs := ia64_ksyms.o unwind.o obj-y := acpi.o entry.o gate.o efi.o efi_stub.o ia64_ksyms.o irq.o irq_ia64.o irq_lsapic.o ivt.o \ machvec.o pal.o process.o perfmon.o ptrace.o sal.o salinfo.o semaphore.o setup.o \
Keith> I am not happy with the kludge that avoids the deadlock on Keith> script-> lock, anybody got a better solution? The kludge Keith> assumes script-> that the first field in an ia64 rwsem is a Keith> spinlock. I have hit this unwind deadlock a couple of times Keith> during processing of asynchronous MCA events, so I want it Keith> fixed.
What I did for libunwind is to avoid deadlock by falling back to uncached unwinding if necessary. That is, if a lock is taken, it just creates an unwind script on the local stack.
It would be good to replace the built-in kernel unwinder with something based on libunwind. That would make it much easier to keep the code in sync (and libunwind is much better tested). I have been toying with the idea of doing this for 2.7, but it hasn't been very high priority to me because, for the most part, the kernel unwinder is good enough.
--david
arch/ia64/kernel/unwind.c Mon, 23 Feb 2004 12:38:43 +1100 kaos (linux-2.4/r/c/42_unwind.c 1.1.2.1.1.2.3.1.1.1.1.3.1.1.1.2 644) script_new (unsigned long ip) · line 1278
Quoted 10 lines · Keith Owens
The unwind code in 2.4.25 has drifted away from the 2.6.3 version, including some missing bug fixes.
arch/ia64/kernel/unwind.c Mon, 23 Feb 2004 12:38:43 +1100 kaos (linux-2.4/r/c/42_unwind.c 1.1.2.1.1.2.3.1.1.1.1.3.1.1.1.2 644) renamed from arch/ia64/kernel/unwind.c Wed, 11 Feb 2004 11:17:55 +1100 kaos (linux-2.4/r/c/42_unwind.c 1.1.2.1.1.2.3.1.1.1.1.3.1.1.1.2 644) +7
-0+ /* Kludge: 2.4 has down_write_trylock on semaphores but not write_trylock on + * spinlocks, even though they are both in 2.6 and are identical. Pretend + * that script lock is a rw_semaphore so we can use the only 2.4 code that + * avoids a deadlock. KAO. + */ + if (!down_write_trylock((struct rw_semaphore *)(&script->lock))) + return NULL;
Should we consider putting write_trylock() in 2.4? It looks like i386, x86_64, and ppc64 already have it.
We also have this diff wrt. 2.6:
@@ -1426,7 +1416,7 @@
case UNW_WHERE_FR:
if (rval <= 5)
- val = unw.preg_index[UNW_REG_F2 + (rval - 1)];
+ val = unw.preg_index[UNW_REG_F2 + (rval - 2)];
else if (rval >= 16 && rval <= 31)
val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
else {You didn't change this, but I'd feel better if I understood why this is different.
I applied your patch, and also twidded the UNW_DEBUG bits to make 2.4 more like 2.6. Thanks for keeping them in sync!
Bjorn
Quoted 7 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Bjorn Helgaas
(quoted diff) +1
-1- val = unw.preg_index[UNW_REG_F2 + (rval - 1)]; + val = unw.preg_index[UNW_REG_F2 + (rval - 2)];You didn't change this, but I'd feel better if I understood why this is different.
It was a typo. The code is needed to handle f2-f5, hence the "- 2".
--david
Quoted 4 lines · Bjorn Helgaas
Quoted 2 lines · Keith Owens
The unwind code in 2.4.25 has drifted away from the 2.6.3 version, including some missing bug fixes.
Quoted 10 lines
arch/ia64/kernel/unwind.c Mon, 23 Feb 2004 12:38:43 +1100 kaos (linux-2.4/r/c/42_unwind.c 1.1.2.1.1.2.3.1.1.1.1.3.1.1.1.2 644) script_new (unsigned long ip) · line 1278
Quoted 7 lines
arch/ia64/kernel/unwind.c Mon, 23 Feb 2004 12:38:43 +1100 kaos (linux-2.4/r/c/42_unwind.c 1.1.2.1.1.2.3.1.1.1.1.3.1.1.1.2 644) renamed from arch/ia64/kernel/unwind.c Wed, 11 Feb 2004 11:17:55 +1100 kaos (linux-2.4/r/c/42_unwind.c 1.1.2.1.1.2.3.1.1.1.1.3.1.1.1.2 644) +7
-0+ /* Kludge: 2.4 has down_write_trylock on semaphores but not write_trylock on + * spinlocks, even though they are both in 2.6 and are identical. Pretend + * that script lock is a rw_semaphore so we can use the only 2.4 code that + * avoids a deadlock. KAO. + */ + if (!down_write_trylock((struct rw_semaphore *)(&script->lock))) + return NULL;Should we consider putting
write_trylock()in 2.4? It looks like i386,x86_64, and ppc64 already have it.
Good idea, I will do a patch once you push your bk tree.
Quoted 12 lines
We also have this diff wrt. 2.6:
(quoted diff) +1
-1@@ -1426,7 +1416,7 @@ case UNW_WHERE_FR: if (rval <= 5) - val = unw.preg_index[UNW_REG_F2 + (rval - 1)]; + val = unw.preg_index[UNW_REG_F2 + (rval - 2)]; else if (rval >= 16 && rval <= 31) val = unw.preg_index[UNW_REG_F16 + (rval - 16)]; else {
Quoted 2 lines
You didn't change this, but I'd feel better if I understood why this is different.
2.6 is correct, it should be (rval - 2) in both trees.
Quoted 9 lines · David Mosberger
Quoted 7 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Bjorn Helgaas
(quoted diff) +1
-1- val = unw.preg_index[UNW_REG_F2 + (rval - 1)]; + val = unw.preg_index[UNW_REG_F2 + (rval - 2)];You didn't change this, but I'd feel better if I understood why this is different.
It was a typo. The code is needed to handle f2-f5, hence the "- 2".
Ah, and I bet that's the one you mentioned on 2/23 with this link:
http://lia64.bkbits.net:8080/to-linus-2.5/[email protected]
(which no longer points the right place -- rats, bitten again by the fact that BK cset numbers change after the fact :-()
Thanks for straightening me out. I'll apply the following patch to 2.4 so it will be the same as 2.6 in this regard:
=== arch/ia64/kernel/unwind.c 1.30 vs edited ==--- 1.30/arch/ia64/kernel/unwind.c Wed Mar 3 16:51:27 2004
+++ edited/arch/ia64/kernel/unwind.c Wed Mar 3 17:33:27 2004
@@ -1420,7 +1420,7 @@
case UNW_WHERE_FR:
if (rval <= 5)
- val = unw.preg_index[UNW_REG_F2 + (rval - 1)]; + val = unw.preg_index[UNW_REG_F2 + (rval - 2)];
else if (rval >= 16 && rval <= 31)
val = unw.preg_index[UNW_REG_F16 + (rval - 16)];
else {
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Bjorn Helgaas
Bjorn> Ah, and I bet that's the one you mentioned on 2/23 with this Bjorn> link: http://lia64.bkbits.net:8080/to-linus-2.5/[email protected]
Bjorn> (which no longer points the right place -- rats, bitten again Bjorn> by the fact that BK cset numbers change after the fact :-()
Argh. Maybe we can use the stable cset numbers, but they're awfully long.
--david