A recent patch (https://lkml.org/lkml/2014/1/15/42) enables multiple processors in the crash kernel.
To do this safely the crash kernel needs to know which CPU was the 1st kernel BSP (bootstrap processor) so that the crash kernel will NOT send the BSP an INIT. If the crash kernel sends an INIT to the 1st kernel BSP, some systems may reset or hang.
The EFI spec doesn't require that any particular processor is chosen as the BSP and the CPU (and its apic id) can change from one boot to the next. Hence automating the selection of CPU to disable if the system would panic is desired.
This patch updates the kdumpctl script to get the "initial apicid" of CPU 0 in the first kernel and will pass this as the "disable_cpu_apicid=" arguement to kexec if it wasn't explicitly set in /etc/sysconfig/kdump KDUMP_COMMANDLINE_APPEND.
CPU 0 is chosen as it is the processor thats execute the OS initialization code and hence was the BSP as per x86 SDM (Vol 3a Section 8.4.)
See associated Red Hat Bugzilla(s) for additional background material:
https://bugzilla.redhat.com/show_bug.cgi?id=1059031 https://bugzilla.redhat.com/show_bug.cgi?id=980621 --- kdumpctl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/kdumpctl b/kdumpctl index 46ae633..0f6cd20 100755 --- a/kdumpctl +++ b/kdumpctl @@ -208,6 +208,26 @@ function need_64bit_headers() print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'` }
+# This function supplies argument disable_cpu_apicid if +# not explicitly specified in KDUMP_COMMANDLINE_APPEND. +# It will be the "initial apicid" of CPU 0 if it exists. + +function disable_apicid() +{ + local cmdline=${KDUMP_COMMANDLINE_APPEND/"disable_cpu_apicid"/":"} + + if [ "$cmdline" != "$KDUMP_COMMANDLINE_APPEND" ] ; then + return 0 + fi + + awk ' \ + BEGIN { CPU = -1; } \ + $1=="processor" && $2==":" { CPU = 0+$NF; } \ + CPU==0 && /initial apicid/ {print "disable_cpu_apicid="$NF;} \ + ' \ + /proc/cpuinfo +} + # Load the kdump kerel specified in /etc/sysconfig/kdump # If none is specified, try to load a kdump kernel with the same version # as the currently running kernel. @@ -251,6 +271,7 @@ function load_kdump() KDUMP_COMMANDLINE=`remove_cmdline_param "$KDUMP_COMMANDLINE" crashkernel hugepages hugepagesz`
KDUMP_COMMANDLINE="${KDUMP_COMMANDLINE} ${KDUMP_COMMANDLINE_APPEND}" + KDUMP_COMMANDLINE="${KDUMP_COMMANDLINE} `disable_apicid`"
$KEXEC $KEXEC_ARGS $standard_kexec_args \ --command-line="$KDUMP_COMMANDLINE" \
On Thu, Feb 20, 2014 at 02:07:37PM -0700, Jerry Hoemann wrote:
A recent patch (https://lkml.org/lkml/2014/1/15/42) enables multiple processors in the crash kernel.
To do this safely the crash kernel needs to know which CPU was the 1st kernel BSP (bootstrap processor) so that the crash kernel will NOT send the BSP an INIT. If the crash kernel sends an INIT to the 1st kernel BSP, some systems may reset or hang.
The EFI spec doesn't require that any particular processor is chosen as the BSP and the CPU (and its apic id) can change from one boot to the next. Hence automating the selection of CPU to disable if the system would panic is desired.
This patch updates the kdumpctl script to get the "initial apicid" of CPU 0 in the first kernel and will pass this as the "disable_cpu_apicid=" arguement to kexec if it wasn't explicitly set in /etc/sysconfig/kdump KDUMP_COMMANDLINE_APPEND.
CPU 0 is chosen as it is the processor thats execute the OS initialization code and hence was the BSP as per x86 SDM (Vol 3a Section 8.4.)
See associated Red Hat Bugzilla(s) for additional background material:
https://bugzilla.redhat.com/show_bug.cgi?id=1059031 https://bugzilla.redhat.com/show_bug.cgi?id=980621
kdumpctl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/kdumpctl b/kdumpctl index 46ae633..0f6cd20 100755 --- a/kdumpctl +++ b/kdumpctl @@ -208,6 +208,26 @@ function need_64bit_headers() print (strtonum("0x" r[2]) > strtonum("0xffffffff")); }'` }
+# This function supplies argument disable_cpu_apicid if +# not explicitly specified in KDUMP_COMMANDLINE_APPEND. +# It will be the "initial apicid" of CPU 0 if it exists.
+function disable_apicid() +{
- local cmdline=${KDUMP_COMMANDLINE_APPEND/"disable_cpu_apicid"/":"}
- if [ "$cmdline" != "$KDUMP_COMMANDLINE_APPEND" ] ; then
- return 0
- fi
- awk ' \
- BEGIN { CPU = -1; } \
- $1=="processor" && $2==":" { CPU = 0+$NF; } \
^^^ Do we have to do "0 + $NF". Will "$NF" alone not do. I am assuming it $NF contains the value of processor if we are here. You seem to be using $NF directly for initial apicid. Why not do same here.
Or will following work. $1=="processor" && $2==":" && $3=="0" { CPU = 0; } \
- CPU==0 && /initial apicid/ {print "disable_cpu_apicid="$NF;} \
- ' \
- /proc/cpuinfo
+}
# Load the kdump kerel specified in /etc/sysconfig/kdump # If none is specified, try to load a kdump kernel with the same version # as the currently running kernel. @@ -251,6 +271,7 @@ function load_kdump() KDUMP_COMMANDLINE=`remove_cmdline_param "$KDUMP_COMMANDLINE" crashkernel hugepages hugepagesz`
KDUMP_COMMANDLINE="${KDUMP_COMMANDLINE} ${KDUMP_COMMANDLINE_APPEND}"
- KDUMP_COMMANDLINE="${KDUMP_COMMANDLINE} `disable_apicid`"
Hi Jerry,
Can we create a separate function say prepare_cmdline() and move all the following processing there.
if [ -z "$KDUMP_COMMANDLINE" ] then KDUMP_COMMANDLINE=`cat /proc/cmdline` fi KDUMP_COMMANDLINE=`remove_cmdline_param "$KDUMP_COMMANDLINE" crashkernel hugepages hugepagesz`
KDUMP_COMMANDLINE="${KDUMP_COMMANDLINE} ${KDUMP_COMMANDLINE_APPEND}"
This load_kdump() function is growing so taking code out in a separate function will make it more readable. And then your code to append disable_cpu_apicid can go there.
And I kind of like following construct better.
Write a function just to get initial apic id of boot cpu.
get_boot_cpu_initial_apic_id()
Then write another function to append a parameter to command line. This function will add the parameter if it is not already present.
add_cmdline_param(). First argument can be exisitng command line, second argument could be param to add and third argument could be value of param.
So pseudo code look as follows.
prepare_cmdline() { ... .... id = get_boot_cpu_initial_apic_id() if (id == -1) return;
append_cmdline_param $orig_cmdline "disable_apic_id" $id }
Thanks Vivek