----- "Michael Holzheu" <holzheu(a)linux.vnet.ibm.com> wrote:
Hi Dave,
On Fri, 2010-02-26 at 09:50 -0500, Dave Anderson wrote:
> ----- "Michael Holzheu" <holzheu(a)linux.vnet.ibm.com> wrote:
>
> > Hi Dave,
> >
> > This patch fixes several bugs in the s390 stack backtrace code
> > * Add panic stack as second interrupt stack
> > * Fix printing of access registers (4 bytes instead of 8 bytes)
> > * Use u64 for s390x register 14
> > * Fix interrupt stack handling for s390x (use 160 byte overhead
> > instead of 96)
>
> The patch looks OK upon first glance -- can you verify that it's
> absolutely backwards-compatible to earlier kernel versions?
I tested vanilla 2.6.32, RHEL5, SLES10 and SLES11.
But I found a bug with RHEL4:
OK good -- I'm glad I asked. I note that RHEL3 doesn't even have
a "panic_stack" member. That being the case, this won't work as
planned:
stack_addr = ULONG(lc + MEMBER_OFFSET("_lowcore", stack_name));
if (stack_addr == 0)
return;
because MEMBER_OFFSET() will return a -1, which will get used as
an offset to add to "lc", and will quietly read the wrong data.
Dave
Older Linux kernels for s390 can be built so that the panic stack is
not set (CONFIG_CHECK_STACK kernel built option):
*(lowcore_ptr[i]) = S390_lowcore;
lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE);
#ifdef CONFIG_CHECK_STACK
stack = __get_free_pages(GFP_KERNEL,0);
if (stack == 0ULL)
panic("smp_boot_cpus failed to allocate memory\n");
lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE);
#endif
RHEL4 has not defined CONFIG_CHECK_STACK. Therefore the following
patch adds a check, so that the panic stack is only used, when
it is there.
---
s390.c | 2 ++
s390x.c | 2 ++
2 files changed, 4 insertions(+)
--- a/s390.c
+++ b/s390.c
@@ -581,6 +581,8 @@ static void s390_get_int_stack(char *sta
if (!MEMBER_EXISTS("_lowcore", stack_name))
return;
stack_addr = ULONG(lc + MEMBER_OFFSET("_lowcore", stack_name));
+ if (stack_addr == 0)
+ return;
readmem(stack_addr - INT_STACK_SIZE, KVADDR, int_stack,
INT_STACK_SIZE, stack_name, FAULT_ON_ERROR);
*start = stack_addr - INT_STACK_SIZE;
--- a/s390x.c
+++ b/s390x.c
@@ -813,6 +813,8 @@ static void s390x_get_int_stack(char *st
if (!MEMBER_EXISTS("_lowcore", stack_name))
return;
stack_addr = ULONG(lc + MEMBER_OFFSET("_lowcore", stack_name));
+ if (stack_addr == 0)
+ return;
readmem(stack_addr - INT_STACK_SIZE, KVADDR, int_stack,
INT_STACK_SIZE, stack_name, FAULT_ON_ERROR);
*start = stack_addr - INT_STACK_SIZE;