Fix for Linux 3.11 and later ARM kernels, in which all non-panicking

cpus offline themselves during a kdump procedure.  This causes an
invalid cpu count determination during crash session initialization
from an ARM vmcore.  The patch utilizes the cpu count found in the
cpu_active_map if it is greater than the count in the cpu_online_map.
In addition, the maximum NR_CPUS value for the ARM architecture has
been raised from 4 to 32.
(sdu.liu@huawei.com)
This commit is contained in:
Dave Anderson 2014-04-28 15:45:51 -04:00
parent a91e410866
commit 8bff022b52
9 changed files with 98 additions and 39 deletions

2
arm.c
View File

@ -1518,7 +1518,7 @@ arm_display_machine_stats(void)
static int
arm_get_smp_cpus(void)
{
return get_cpus_online();
return MAX(get_cpus_active(), get_cpus_online());
}
/*

7
defs.h
View File

@ -131,7 +131,7 @@
#define NR_CPUS (512)
#endif
#ifdef ARM
#define NR_CPUS (4)
#define NR_CPUS (32)
#endif
#ifdef ARM64
#define NR_CPUS (4096) /* TBD */
@ -658,6 +658,10 @@ struct kernel_table { /* kernel data */
#define PRESENT (0x2)
#define ONLINE (0x4)
#define NMI (0x8)
#define POSSIBLE_MAP (POSSIBLE)
#define PRESENT_MAP (PRESENT)
#define ONLINE_MAP (ONLINE)
#define ACTIVE_MAP (0x10)
int BUG_bytes;
ulong xen_flags;
#define WRITABLE_PAGE_TABLES (0x1)
@ -4795,6 +4799,7 @@ void set_cpu(int);
void clear_machdep_cache(void);
struct stack_hook *gather_text_list(struct bt_info *);
int get_cpus_online(void);
int get_cpus_active(void);
int get_cpus_present(void);
int get_cpus_possible(void);
int get_highest_cpu_online(void);

View File

@ -119,7 +119,7 @@ map_cpus_to_prstatus_kdump_cmprs(void)
nrcpus = (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS);
for (i = 0, j = 0; i < nrcpus; i++) {
if (in_cpu_map(ONLINE, i)) {
if (in_cpu_map(ONLINE_MAP, i)) {
dd->nt_prstatus_percpu[i] = nt_ptr[j++];
dd->num_prstatus_notes =
MAX(dd->num_prstatus_notes, i+1);
@ -1193,7 +1193,7 @@ get_diskdump_panic_task(void)
if (kernel_symbol_exists("crashing_cpu") &&
cpu_map_addr("online")) {
get_symbol_data("crashing_cpu", sizeof(int), &i);
if ((i >= 0) && in_cpu_map(ONLINE, i)) {
if ((i >= 0) && in_cpu_map(ONLINE_MAP, i)) {
if (CRASHDEBUG(1))
error(INFO, "get_diskdump_panic_task: "
"active_set[%d]: %lx\n",

View File

@ -795,9 +795,10 @@ cpu_maps_init(void)
ulong cpu_flag;
char *name;
} mapinfo[] = {
{ POSSIBLE, "possible" },
{ PRESENT, "present" },
{ ONLINE, "online" },
{ POSSIBLE_MAP, "possible" },
{ PRESENT_MAP, "present" },
{ ONLINE_MAP, "online" },
{ ACTIVE_MAP, "active" },
};
if ((len = STRUCT_SIZE("cpumask_t")) < 0)
@ -864,26 +865,33 @@ in_cpu_map(int map, int cpu)
switch (map)
{
case POSSIBLE:
case POSSIBLE_MAP:
if (!cpu_map_addr("possible")) {
error(INFO, "cpu_possible_map does not exist\n");
return FALSE;
}
return (kt->cpu_flags[cpu] & POSSIBLE);
return (kt->cpu_flags[cpu] & POSSIBLE_MAP);
case PRESENT:
case PRESENT_MAP:
if (!cpu_map_addr("present")) {
error(INFO, "cpu_present_map does not exist\n");
return FALSE;
}
return (kt->cpu_flags[cpu] & PRESENT);
return (kt->cpu_flags[cpu] & PRESENT_MAP);
case ONLINE:
case ONLINE_MAP:
if (!cpu_map_addr("online")) {
error(INFO, "cpu_online_map does not exist\n");
return FALSE;
}
return (kt->cpu_flags[cpu] & ONLINE);
return (kt->cpu_flags[cpu] & ONLINE_MAP);
case ACTIVE_MAP:
if (!cpu_map_addr("active")) {
error(INFO, "cpu_active_map does not exist\n");
return FALSE;
}
return (kt->cpu_flags[cpu] & ACTIVE_MAP);
}
return FALSE;
@ -5321,7 +5329,7 @@ dump_kernel_table(int verbose)
fprintf(fp, " cpu_possible_map: ");
if (cpu_map_addr("possible")) {
for (i = 0; i < nr_cpus; i++) {
if (kt->cpu_flags[i] & POSSIBLE)
if (kt->cpu_flags[i] & POSSIBLE_MAP)
fprintf(fp, "%d ", i);
}
fprintf(fp, "\n");
@ -5330,7 +5338,7 @@ dump_kernel_table(int verbose)
fprintf(fp, " cpu_present_map: ");
if (cpu_map_addr("present")) {
for (i = 0; i < nr_cpus; i++) {
if (kt->cpu_flags[i] & PRESENT)
if (kt->cpu_flags[i] & PRESENT_MAP)
fprintf(fp, "%d ", i);
}
fprintf(fp, "\n");
@ -5339,12 +5347,22 @@ dump_kernel_table(int verbose)
fprintf(fp, " cpu_online_map: ");
if (cpu_map_addr("online")) {
for (i = 0; i < nr_cpus; i++) {
if (kt->cpu_flags[i] & ONLINE)
if (kt->cpu_flags[i] & ONLINE_MAP)
fprintf(fp, "%d ", i);
}
fprintf(fp, "\n");
} else
fprintf(fp, "(does not exist)\n");
fprintf(fp, " cpu_active_map: ");
if (cpu_map_addr("active")) {
for (i = 0; i < nr_cpus; i++) {
if (kt->cpu_flags[i] & ACTIVE_MAP)
fprintf(fp, "%d ", i);
}
fprintf(fp, "\n");
} else
fprintf(fp, "(does not exist)\n");
no_cpu_flags:
fprintf(fp, " vmcoreinfo: \n");
fprintf(fp, " log_buf_SYMBOL: %lx\n", kt->vmcoreinfo.log_buf_SYMBOL);
@ -7972,6 +7990,40 @@ get_highest_cpu_online()
return highest;
}
/*
* If it exists, return the number of cpus in the cpu_active_map.
*/
int
get_cpus_active()
{
int i, len, active;
char *buf;
ulong *maskptr, addr;
if (!(addr = cpu_map_addr("active")))
return 0;
len = cpu_map_size("active");
buf = GETBUF(len);
active = 0;
if (readmem(addr, KVADDR, buf, len,
"cpu_active_map", RETURN_ON_ERROR)) {
maskptr = (ulong *)buf;
for (i = 0; i < (len/sizeof(ulong)); i++, maskptr++)
active += count_bits_long(*maskptr);
if (CRASHDEBUG(1))
error(INFO, "get_cpus_active: active: %d\n", active);
}
FREEBUF(buf);
return active;
}
/*
* If it exists, return the number of cpus in the cpu_present_map.
*/

View File

@ -92,7 +92,7 @@ map_cpus_to_prstatus(void)
nrcpus = (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS);
for (i = 0, j = 0; i < nrcpus; i++) {
if (in_cpu_map(ONLINE, i))
if (in_cpu_map(ONLINE_MAP, i))
nd->nt_prstatus_percpu[i] = nt_ptr[j++];
}
@ -769,7 +769,7 @@ get_netdump_panic_task(void)
crashing_cpu = -1;
if (kernel_symbol_exists("crashing_cpu")) {
get_symbol_data("crashing_cpu", sizeof(int), &i);
if ((i >= 0) && in_cpu_map(ONLINE, i)) {
if ((i >= 0) && in_cpu_map(ONLINE_MAP, i)) {
crashing_cpu = i;
if (CRASHDEBUG(1))
error(INFO,

6
ppc.c
View File

@ -1,8 +1,8 @@
/* ppc.c - core analysis suite
*
* Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
* Copyright (C) 2002-2007, 2010-2013 David Anderson
* Copyright (C) 2002-2007, 2010-2013 Red Hat, Inc. All rights reserved.
* Copyright (C) 2002-2007, 2010-2014 David Anderson
* Copyright (C) 2002-2007, 2010-2014 Red Hat, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -2036,7 +2036,7 @@ ppc_relocate_nt_prstatus_percpu(void **nt_prstatus_percpu,
*num_prstatus_notes = 0;
nrcpus = (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS);
for (i = 0, j = 0; i < nrcpus; i++) {
if (!in_cpu_map(ONLINE, i))
if (!in_cpu_map(ONLINE_MAP, i))
continue;
if (verify_crash_note_in_kernel(i))
nt_prstatus_percpu[i] = nt_ptr[j++];

22
ppc64.c
View File

@ -1,7 +1,7 @@
/* ppc64.c -- core analysis suite
*
* Copyright (C) 2004-2013 David Anderson
* Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004-2014 David Anderson
* Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
* Copyright (C) 2004, 2006 Haren Myneni, IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
@ -2861,16 +2861,18 @@ ppc64_get_cpu_map(void)
int map;
if (cpu_map_addr("possible"))
map = POSSIBLE;
map = POSSIBLE_MAP;
else if (cpu_map_addr("present"))
map = PRESENT;
map = PRESENT_MAP;
else if (cpu_map_addr("online"))
map = ONLINE;
map = ONLINE_MAP;
else if (cpu_map_addr("active"))
map = ACTIVE_MAP;
else {
map = 0;
error(FATAL,
"PPC64: cannot find 'cpu_possible_map' or\
'cpu_present_map' or 'cpu_online_map' symbols\n");
"PPC64: cannot find 'cpu_possible_map', "
"'cpu_present_map', 'cpu_online_map' or 'cpu_active_map' symbols\n");
}
return map;
}
@ -2911,15 +2913,15 @@ ppc64_init_cpu_info(void)
}
switch (map)
{
case POSSIBLE:
case POSSIBLE_MAP:
if (cpus > kt->cpus) {
i = get_highest_cpu_online() + 1;
if (i > kt->cpus)
kt->cpus = i;
}
break;
case ONLINE:
case PRESENT:
case ONLINE_MAP:
case PRESENT_MAP:
kt->cpus = cpus;
break;
}

8
s390.c
View File

@ -1,8 +1,8 @@
/* s390.c - core analysis suite
*
* Copyright (C) 2001, 2002 Mission Critical Linux, Inc.
* Copyright (C) 2002-2006, 2009-2010, 2012-2013 David Anderson
* Copyright (C) 2002-2006, 2009-2010, 2012-2013 Red Hat, Inc. All rights reserved.
* Copyright (C) 2002-2006, 2009-2010, 2012-2014 David Anderson
* Copyright (C) 2002-2006, 2009-2010, 2012-2014 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005, 2006, 2010 Michael Holzheu, IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
@ -558,7 +558,7 @@ s390_has_cpu(struct bt_info *bt)
{
int cpu = bt->tc->processor;
if (is_task_active(bt->task) && (kt->cpu_flags[cpu] & ONLINE))
if (is_task_active(bt->task) && (kt->cpu_flags[cpu] & ONLINE_MAP))
return TRUE;
else
return FALSE;
@ -619,7 +619,7 @@ s390_back_trace_cmd(struct bt_info *bt)
error(WARNING,
"instruction pointer argument ignored on this architecture!\n");
}
if (is_task_active(bt->task) && !(kt->cpu_flags[cpu] & ONLINE)) {
if (is_task_active(bt->task) && !(kt->cpu_flags[cpu] & ONLINE_MAP)) {
fprintf(fp, " CPU offline\n");
return;
}

View File

@ -1,8 +1,8 @@
/* s390.c - core analysis suite
*
* Copyright (C) 2001, 2002 Mission Critical Linux, Inc.
* Copyright (C) 2002-2006, 2009-2013 David Anderson
* Copyright (C) 2002-2006, 2009-2013 Red Hat, Inc. All rights reserved.
* Copyright (C) 2002-2006, 2009-2014 David Anderson
* Copyright (C) 2002-2006, 2009-2014 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005, 2006, 2010-2013 Michael Holzheu, IBM Corporation
*
* This program is free software; you can redistribute it and/or modify
@ -872,7 +872,7 @@ s390x_has_cpu(struct bt_info *bt)
{
int cpu = bt->tc->processor;
if (is_task_active(bt->task) && (kt->cpu_flags[cpu] & ONLINE))
if (is_task_active(bt->task) && (kt->cpu_flags[cpu] & ONLINE_MAP))
return TRUE;
else
return FALSE;
@ -1165,7 +1165,7 @@ static void s390x_back_trace_cmd(struct bt_info *bt)
error(WARNING,
"instruction pointer argument ignored on this architecture!\n");
}
if (is_task_active(bt->task) && !(kt->cpu_flags[cpu] & ONLINE)) {
if (is_task_active(bt->task) && !(kt->cpu_flags[cpu] & ONLINE_MAP)) {
fprintf(fp, " CPU offline\n");
return;
}