Browse Source

kexec-tools package update

Signed-off-by: basebuilder_pel7x64builder0 <basebuilder@powerel.org>
master
basebuilder_pel7x64builder0 6 years ago
parent
commit
4125f48a18
  1. 4
      SOURCES/98-kexec.rules
  2. 30
      SOURCES/dracut-kdump-capture.service
  3. 28
      SOURCES/dracut-kdump-emergency.service
  4. 14
      SOURCES/dracut-kdump-emergency.target
  5. 34
      SOURCES/dracut-kdump-error-handler.service
  6. 10
      SOURCES/dracut-kdump-error-handler.sh
  7. 204
      SOURCES/dracut-kdump.sh
  8. 782
      SOURCES/dracut-module-setup.sh
  9. 28
      SOURCES/dracut-monitor_dd_progress
  10. 251
      SOURCES/fadump-howto.txt
  11. 22
      SOURCES/kdump-dep-generator.sh
  12. 91
      SOURCES/kdump-in-cluster-environment.txt
  13. 165
      SOURCES/kdump-lib-initramfs.sh
  14. 520
      SOURCES/kdump-lib.sh
  15. 163
      SOURCES/kdump.conf
  16. 344
      SOURCES/kdump.conf.5
  17. 14
      SOURCES/kdump.service
  18. 31
      SOURCES/kdump.sysconfig
  19. 33
      SOURCES/kdump.sysconfig.aarch64
  20. 40
      SOURCES/kdump.sysconfig.i386
  21. 32
      SOURCES/kdump.sysconfig.ia64
  22. 42
      SOURCES/kdump.sysconfig.ppc64
  23. 42
      SOURCES/kdump.sysconfig.ppc64le
  24. 43
      SOURCES/kdump.sysconfig.s390x
  25. 40
      SOURCES/kdump.sysconfig.x86_64
  26. 1323
      SOURCES/kdumpctl
  27. 44
      SOURCES/kdumpctl.8
  28. 730
      SOURCES/kexec-kdump-howto.txt
  29. 40
      SOURCES/kexec-tools-2.0.14-Only-print-debug-message-when-failed-to-serach-for-k.patch
  30. 76
      SOURCES/kexec-tools-2.0.14-arm64-identify-PHYS_OFFSET-correctly.patch
  31. 52
      SOURCES/kexec-tools-2.0.14-arm64-kdump-Add-support-for-binary-image-files.patch
  32. 282
      SOURCES/kexec-tools-2.0.14-arm64-kdump-add-DT-properties-to-crash-dump-kernel-s.patch
  33. 191
      SOURCES/kexec-tools-2.0.14-arm64-kdump-add-elf-core-header-segment.patch
  34. 202
      SOURCES/kexec-tools-2.0.14-arm64-kdump-identify-memory-regions.patch
  35. 140
      SOURCES/kexec-tools-2.0.14-arm64-kdump-set-up-kernel-image-segment.patch
  36. 35
      SOURCES/kexec-tools-2.0.14-arm64-kdump-set-up-other-segments.patch
  37. 43
      SOURCES/kexec-tools-2.0.14-build_mem_phdrs-check-if-p_paddr-is-invalid.patch
  38. 32
      SOURCES/kexec-tools-2.0.14-kexec-Increase-the-upper-limit-for-RAM-segments.patch
  39. 79
      SOURCES/kexec-tools-2.0.14-kexec-exntend-the-semantics-of-kexec_iomem_for_each_.patch
  40. 187
      SOURCES/kexec-tools-2.0.14-kexec-generalize-and-rename-get_kernel_stext_sym.patch
  41. 94
      SOURCES/kexec-tools-2.0.14-kexec-powerpc-fix-command-line-overflow-error.patch
  42. 47
      SOURCES/kexec-tools-2.0.14-makedumpfile-elf_info-kcore-check-for-invalid-physic.patch
  43. 47
      SOURCES/kexec-tools-2.0.14-makedumpfile-initial-call-cache_init-a-bit-early.patch
  44. 45
      SOURCES/kexec-tools-2.0.14-makedumpfile-makedumpfile-Correct-the-calculation-of.patch
  45. 57
      SOURCES/kexec-tools-2.0.14-makedumpfile-makedumpfile-Discard-process_dump_load.patch
  46. 303
      SOURCES/kexec-tools-2.0.14-makedumpfile-makedumpfile-add-runtime-kaslr-offset-if-it-exists.patch
  47. 83
      SOURCES/kexec-tools-2.0.14-makedumpfile-sadump-set-info-page_size-before-cache_init.patch
  48. 41
      SOURCES/kexec-tools-2.0.14-makedumpfile-show_mem_usage-calculate-page-offset-af.patch
  49. 85
      SOURCES/kexec-tools-2.0.14-makedumpfile-x86_64-calculate-page_offset-in-case-of-re-filtering.patch
  50. 47
      SOURCES/kexec-tools-2.0.14-makedumpfile-x86_64-check-physical-address-in-PT_LOA.patch
  51. 67
      SOURCES/kexec-tools-2.0.14-ppc64-Reduce-number-of-ELF-LOAD-segments.patch
  52. 52
      SOURCES/kexec-tools-2.0.14-x86-Support-large-number-of-memory-ranges.patch
  53. 875
      SOURCES/kexec-tools-2.0.15-makedumpfile-Add-a-new-helper-file-tools.c-that-provides-some-use.patch
  54. 39
      SOURCES/kexec-tools-2.0.15-makedumpfile-Check-if-clock_gettime-requires-lrt.patch
  55. 36
      SOURCES/kexec-tools-2.0.15-makedumpfile-Documentation-Update-documentation-regarding-mem-usa.patch
  56. 55
      SOURCES/kexec-tools-2.0.15-makedumpfile-Fix-SECTION_MAP_MASK-for-kernel-v.13.patch
  57. 79
      SOURCES/kexec-tools-2.0.15-makedumpfile-Fix-array-index-out-of-bound-exception.patch
  58. 124
      SOURCES/kexec-tools-2.0.15-makedumpfile-Fix-kernel_version-variable-being-uninitia.patch
  59. 75
      SOURCES/kexec-tools-2.0.15-makedumpfile-Fix-off-by-one-errors-in-exclude_segment.patch
  60. 35
      SOURCES/kexec-tools-2.0.15-makedumpfile-Fix-physical-to-virtual-conversion-in-excl.patch
  61. 93
      SOURCES/kexec-tools-2.0.15-makedumpfile-Introduce-vtop4_x86_64_pagetable.patch
  62. 48
      SOURCES/kexec-tools-2.0.15-makedumpfile-PATCH-Support-newer-kernels.patch
  63. 68
      SOURCES/kexec-tools-2.0.15-makedumpfile-Support-symbol-__cpu_online_mask.patch
  64. 139
      SOURCES/kexec-tools-2.0.15-makedumpfile-Use-integer-arithmetics-for-th.patch
  65. 456
      SOURCES/kexec-tools-2.0.15-makedumpfile-Use-monotonic-clock-to-calculate-ETA-and-s.patch
  66. 152
      SOURCES/kexec-tools-2.0.15-makedumpfile-arm64-Add-support-to-read-symbols-like-_stext-from-p.patch
  67. 41
      SOURCES/kexec-tools-2.0.15-makedumpfile-arm64-Fix-calculation-of-page_offset-in-case-we-are-.patch
  68. 71
      SOURCES/kexec-tools-2.0.15-makedumpfile-book3s-ppc64-Lower-the-max-real-address-to-53-bits.patch
  69. 92
      SOURCES/kexec-tools-2.0.15-makedumpfile-fix-for-hugepages-filtering.patch
  70. 169
      SOURCES/kexec-tools-2.0.15-makedumpfile-ppc64-get-the-info-of-mem-reserved-for-.patch
  71. 30
      SOURCES/kexec-tools-2.0.15-makedumpfile-ppc64-set-page_offset-in-get_versiondep.patch
  72. 359
      SOURCES/kexec-tools-2.0.15-makedumpfile-sadump-Fix-a-KASLR-problem-of-sadump-wh.patch
  73. 262
      SOURCES/kexec-tools-2.0.15-makedumpfile-sadump-Fix-a-KASLR-problem-of-sadump.patch
  74. 87
      SOURCES/kexec-tools-2.0.15-makedumpfile-sadump-Fix-a-problem-of-PTI-enabled-kernel.patch
  75. 106
      SOURCES/kexec-tools-2.0.15-makedumpfile-when-refiltering-initialize-refiltered-bitm.patch
  76. 48
      SOURCES/kexec-tools-2.0.15-makedumpfile-x86_64-Take-care-of-init_level4_pgt-rename-.patch
  77. 131
      SOURCES/kexec-tools-2.0.15-ppc64-avoid-adding-coherent-memory-regio.patch
  78. 141
      SOURCES/kexec-tools-2.0.15-ppc64-fix-command-line-overflow-error.patch
  79. 123
      SOURCES/kexec-tools-2.0.15-ppc64-fix-how-RMA-top-is-deduced.patch
  80. 28
      SOURCES/kexec-tools-2.0.15-ppc64-fix-leak-while-checking-for-cohere.patch
  81. 17
      SOURCES/kexec-tools-2.0.3-disable-kexec-test.patch
  82. 521
      SOURCES/mkdumprd
  83. 33
      SOURCES/mkdumprd.8
  84. 128
      SOURCES/supported-kdump-targets.txt
  85. 1844
      SPECS/kexec-tools.spec

4
SOURCES/98-kexec.rules

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
SUBSYSTEM=="cpu", ACTION=="add", PROGRAM="/bin/systemctl try-restart kdump.service"
SUBSYSTEM=="cpu", ACTION=="remove", PROGRAM="/bin/systemctl try-restart kdump.service"
SUBSYSTEM=="memory", ACTION=="online", PROGRAM="/bin/systemctl try-restart kdump.service"
SUBSYSTEM=="memory", ACTION=="offline", PROGRAM="/bin/systemctl try-restart kdump.service"

30
SOURCES/dracut-kdump-capture.service

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.

[Unit]
Description=Kdump Vmcore Save Service
After=initrd.target initrd-parse-etc.service sysroot.mount
After=dracut-initqueue.service dracut-pre-mount.service dracut-mount.service dracut-pre-pivot.service
Before=initrd-cleanup.service
ConditionPathExists=/etc/initrd-release
OnFailure=emergency.target
OnFailureIsolate=yes

[Service]
Environment=DRACUT_SYSTEMD=1
Environment=NEWROOT=/sysroot
Type=oneshot
ExecStart=/bin/kdump.sh
StandardInput=null
StandardOutput=syslog
StandardError=syslog+console
KillMode=process
RemainAfterExit=yes

# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
# terminates cleanly.
KillSignal=SIGHUP

28
SOURCES/dracut-kdump-emergency.service

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.

# This service will be placed in kdump initramfs and replace both the systemd
# emergency service and dracut emergency shell. IOW, any emergency will be
# kick this service and in turn isolating to kdump error handler.

[Unit]
Description=Kdump Emergency
DefaultDependencies=no
IgnoreOnIsolate=yes

[Service]
ExecStart=/usr/bin/systemctl --no-block isolate kdump-error-handler.service
Type=oneshot
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
KillMode=process
IgnoreSIGPIPE=no

# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
# terminates cleanly.
KillSignal=SIGHUP

14
SOURCES/dracut-kdump-emergency.target

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.

[Unit]
Description=Emergency Mode
Documentation=man:systemd.special(7)
Requires=emergency.service
After=emergency.service
AllowIsolate=yes
IgnoreOnIsolate=yes

34
SOURCES/dracut-kdump-error-handler.service

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.

# This service will run the real kdump error handler code. Executing the
# default action configured in kdump.conf

[Unit]
Description=Kdump Error Handler
DefaultDependencies=no
After=systemd-vconsole-setup.service
Wants=systemd-vconsole-setup.service
AllowIsolate=yes

[Service]
Environment=HOME=/
Environment=DRACUT_SYSTEMD=1
Environment=NEWROOT=/sysroot
WorkingDirectory=/
ExecStart=/bin/kdump-error-handler.sh
ExecStopPost=-/usr/bin/systemctl --fail --no-block default
Type=oneshot
StandardInput=tty-force
StandardOutput=inherit
StandardError=inherit
KillMode=process
IgnoreSIGPIPE=no

# Bash ignores SIGTERM, so we send SIGHUP instead, to ensure that bash
# terminates cleanly.
KillSignal=SIGHUP

10
SOURCES/dracut-kdump-error-handler.sh

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
#!/bin/sh

. /lib/kdump-lib-initramfs.sh

set -o pipefail
export PATH=$PATH:$KDUMP_SCRIPT_DIR

get_kdump_confs
do_default_action
do_final_action

204
SOURCES/dracut-kdump.sh

@ -0,0 +1,204 @@ @@ -0,0 +1,204 @@
#!/bin/sh

# continue here only if we have to save dump.
if [ -f /etc/fadump.initramfs ] && [ ! -f /proc/device-tree/rtas/ibm,kernel-dump ]; then
exit 0
fi

exec &> /dev/console
. /lib/dracut-lib.sh
. /lib/kdump-lib-initramfs.sh

set -o pipefail
DUMP_RETVAL=0

export PATH=$PATH:$KDUMP_SCRIPT_DIR

do_dump()
{
local _ret

eval $DUMP_INSTRUCTION
_ret=$?

if [ $_ret -ne 0 ]; then
echo "kdump: saving vmcore failed"
fi

return $_ret
}

do_kdump_pre()
{
if [ -n "$KDUMP_PRE" ]; then
"$KDUMP_PRE"
fi
}

do_kdump_post()
{
if [ -n "$KDUMP_POST" ]; then
"$KDUMP_POST" "$1"
fi
}

add_dump_code()
{
DUMP_INSTRUCTION=$1
}

dump_raw()
{
local _raw=$1

[ -b "$_raw" ] || return 1

echo "kdump: saving to raw disk $_raw"

if ! $(echo -n $CORE_COLLECTOR|grep -q makedumpfile); then
_src_size=`ls -l /proc/vmcore | cut -d' ' -f5`
_src_size_mb=$(($_src_size / 1048576))
monitor_dd_progress $_src_size_mb &
fi

echo "kdump: saving vmcore"
$CORE_COLLECTOR /proc/vmcore | dd of=$_raw bs=$DD_BLKSIZE >> /tmp/dd_progress_file 2>&1 || return 1
sync

echo "kdump: saving vmcore complete"
return 0
}

dump_ssh()
{
local _opt="-i $1 -o BatchMode=yes -o StrictHostKeyChecking=yes"
local _dir="$KDUMP_PATH/$HOST_IP-$DATEDIR"
local _host=$2

echo "kdump: saving to $_host:$_dir"

cat /var/lib/random-seed > /dev/urandom
ssh -q $_opt $_host mkdir -p $_dir || return 1

save_vmcore_dmesg_ssh ${DMESG_COLLECTOR} ${_dir} "${_opt}" $_host

echo "kdump: saving vmcore"

if [ "${CORE_COLLECTOR%%[[:blank:]]*}" = "scp" ]; then
scp -q $_opt /proc/vmcore "$_host:$_dir/vmcore-incomplete" || return 1
ssh $_opt $_host "mv $_dir/vmcore-incomplete $_dir/vmcore" || return 1
else
$CORE_COLLECTOR /proc/vmcore | ssh $_opt $_host "dd bs=512 of=$_dir/vmcore-incomplete" || return 1
ssh $_opt $_host "mv $_dir/vmcore-incomplete $_dir/vmcore.flat" || return 1
fi

echo "kdump: saving vmcore complete"
return 0
}

save_vmcore_dmesg_ssh() {
local _dmesg_collector=$1
local _path=$2
local _opts="$3"
local _location=$4

echo "kdump: saving vmcore-dmesg.txt"
$_dmesg_collector /proc/vmcore | ssh $_opts $_location "dd of=$_path/vmcore-dmesg-incomplete.txt"
_exitcode=$?

if [ $_exitcode -eq 0 ]; then
ssh -q $_opts $_location mv $_path/vmcore-dmesg-incomplete.txt $_path/vmcore-dmesg.txt
echo "kdump: saving vmcore-dmesg.txt complete"
else
echo "kdump: saving vmcore-dmesg.txt failed"
fi
}

get_host_ip()
{
local _host
if is_nfs_dump_target || is_ssh_dump_target
then
kdumpnic=$(getarg kdumpnic=)
[ -z "$kdumpnic" ] && echo "kdump: failed to get kdumpnic!" && return 1
_host=`ip addr show dev $kdumpnic|grep '[ ]*inet'`
[ $? -ne 0 ] && echo "kdump: wrong kdumpnic: $kdumpnic" && return 1
_host=`echo $_host | head -n 1 | cut -d' ' -f2`
_host="${_host%%/*}"
[ -z "$_host" ] && echo "kdump: wrong kdumpnic: $kdumpnic" && return 1
HOST_IP=$_host
fi
return 0
}

read_kdump_conf()
{
if [ ! -f "$KDUMP_CONF" ]; then
echo "kdump: $KDUMP_CONF not found"
return
fi

get_kdump_confs

# rescan for add code for dump target
while read config_opt config_val;
do
# remove inline comments after the end of a directive.
config_val=$(strip_comments $config_val)
case "$config_opt" in
dracut_args)
config_val=$(get_dracut_args_target "$config_val")
[[ -n "$config_val" ]] && add_dump_code "dump_fs $config_val"
;;
ext[234]|xfs|btrfs|minix|nfs)
add_dump_code "dump_fs $config_val"
;;
raw)
add_dump_code "dump_raw $config_val"
;;
ssh)
add_dump_code "dump_ssh $SSH_KEY_LOCATION $config_val"
;;
esac
done < $KDUMP_CONF
}

fence_kdump_notify()
{
if [ -n "$FENCE_KDUMP_NODES" ]; then
$FENCE_KDUMP_SEND $FENCE_KDUMP_ARGS $FENCE_KDUMP_NODES &
fi
}

read_kdump_conf
fence_kdump_notify

get_host_ip
if [ $? -ne 0 ]; then
echo "kdump: get_host_ip exited with non-zero status!"
exit 1
fi

if [ -z "$DUMP_INSTRUCTION" ]; then
add_dump_code "dump_fs $NEWROOT"
fi

do_kdump_pre
if [ $? -ne 0 ]; then
echo "kdump: kdump_pre script exited with non-zero status!"
do_final_action
fi
make_trace_mem "kdump saving vmcore" '1:shortmem' '2+:mem' '3+:slab'
do_dump
DUMP_RETVAL=$?

do_kdump_post $DUMP_RETVAL
if [ $? -ne 0 ]; then
echo "kdump: kdump_post script exited with non-zero status!"
fi

if [ $DUMP_RETVAL -ne 0 ]; then
exit 1
fi

do_final_action

782
SOURCES/dracut-module-setup.sh

@ -0,0 +1,782 @@ @@ -0,0 +1,782 @@
#!/bin/bash

. $dracutfunctions
. /lib/kdump/kdump-lib.sh

if ! [[ -d "${initdir}/tmp" ]]; then
mkdir -p "${initdir}/tmp"
fi

check() {
[[ $debug ]] && set -x
#kdumpctl sets this explicitly
if [ -z "$IN_KDUMP" ] || [ ! -f /etc/kdump.conf ]
then
return 1
fi
return 0
}

depends() {
local _dep="base shutdown"

if [ -n "$( find /sys/devices -name drm )" ] || [ -d /sys/module/hyperv_fb ]; then
_dep="$_dep drm"
fi

if is_generic_fence_kdump -o is_pcs_fence_kdump; then
_dep="$_dep network"
fi

echo $_dep
return 0
}

kdump_to_udev_name() {
local dev="${1//\"/}"

case "$dev" in
UUID=*)
dev=`blkid -U "${dev#UUID=}"`
;;
LABEL=*)
dev=`blkid -L "${dev#LABEL=}"`
;;
esac
echo $(get_persistent_dev "$dev")
}

kdump_is_bridge() {
[ -d /sys/class/net/"$1"/bridge ]
}

kdump_is_bond() {
[ -d /sys/class/net/"$1"/bonding ]
}

kdump_is_team() {
[ -f /usr/bin/teamnl ] && teamnl $1 ports &> /dev/null
}

kdump_is_vlan() {
[ -f /proc/net/vlan/"$1" ]
}

# $1: netdev name
source_ifcfg_file() {
local ifcfg_file

ifcfg_file=$(get_ifcfg_filename $1)
if [ -f "${ifcfg_file}" ]; then
. ${ifcfg_file}
else
dwarning "The ifcfg file of $1 is not found!"
fi
}

# $1: netdev name
kdump_setup_dns() {
local _nameserver _dns
local _dnsfile=${initdir}/etc/cmdline.d/42dns.conf

source_ifcfg_file $1

[ -n "$DNS1" ] && echo "nameserver=$DNS1" > "$_dnsfile"
[ -n "$DNS2" ] && echo "nameserver=$DNS2" >> "$_dnsfile"

while read content;
do
_nameserver=$(echo $content | grep ^nameserver)
[ -z "$_nameserver" ] && continue

_dns=$(echo $_nameserver | cut -d' ' -f2)
[ -z "$_dns" ] && continue

if [ ! -f $_dnsfile ] || [ ! $(cat $_dnsfile | grep -q $_dns) ]; then
echo "nameserver=$_dns" >> "$_dnsfile"
fi
done < "/etc/resolv.conf"
}

#$1: netdev name
#$2: srcaddr
#if it use static ip echo it, or echo null
kdump_static_ip() {
local _netdev="$1" _srcaddr="$2" _ipv6_flag
local _netmask _gateway _ipaddr _target _nexthop

_ipaddr=$(ip addr show dev $_netdev permanent | awk "/ $_srcaddr\/.* /{print \$2}")

if is_ipv6_address $_srcaddr; then
_ipv6_flag="-6"
fi

if [ -n "$_ipaddr" ]; then
_gateway=$(ip $_ipv6_flag route list dev $_netdev | \
awk '/^default /{print $3}' | head -n 1)

if [ "x" != "x"$_ipv6_flag ]; then
# _ipaddr="2002::56ff:feb6:56d5/64", _netmask is the number after "/"
_netmask=${_ipaddr#*\/}
_srcaddr="[$_srcaddr]"
_gateway="[$_gateway]"
else
_netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2)
fi
echo -n "${_srcaddr}::${_gateway}:${_netmask}::"
fi

/sbin/ip $_ipv6_flag route show | grep -v default | grep ".*via.* $_netdev " |\
while read _route; do
_target=`echo $_route | cut -d ' ' -f1`
_nexthop=`echo $_route | cut -d ' ' -f3`
if [ "x" != "x"$_ipv6_flag ]; then
_target="[$_target]"
_nexthop="[$_nexthop]"
fi
echo "rd.route=$_target:$_nexthop:$_netdev"
done >> ${initdir}/etc/cmdline.d/45route-static.conf
}

kdump_get_mac_addr() {
cat /sys/class/net/$1/address
}

#Bonding or team master modifies the mac address
#of its slaves, we should use perm address
kdump_get_perm_addr() {
local addr=$(ethtool -P $1 | sed -e 's/Permanent address: //')
if [ -z "$addr" ] || [ "$addr" = "00:00:00:00:00:00" ]
then
derror "Can't get the permanent address of $1"
else
echo "$addr"
fi
}

# Prefix kernel assigned names with "kdump-". EX: eth0 -> kdump-eth0
# Because kernel assigned names are not persistent between 1st and 2nd
# kernel. We could probably end up with eth0 being eth1, eth0 being
# eth1, and naming conflict happens.
kdump_setup_ifname() {
local _ifname

# If ifname already has 'kdump-' prefix, we must be switching from
# fadump to kdump. Skip prefixing 'kdump-' in this case as adding
# another prefix may truncate the ifname. Since an ifname with
# 'kdump-' is already persistent, this should be fine.
if [[ $1 =~ eth* ]] && [[ ! $1 =~ ^kdump-* ]]; then
_ifname="kdump-$1"
else
_ifname="$1"
fi

echo "$_ifname"
}

kdump_setup_bridge() {
local _netdev=$1
local _brif _dev _mac _kdumpdev
for _dev in `ls /sys/class/net/$_netdev/brif/`; do
_kdumpdev=$_dev
if kdump_is_bond "$_dev"; then
kdump_setup_bond "$_dev"
elif kdump_is_team "$_dev"; then
kdump_setup_team "$_dev"
elif kdump_is_vlan "$_dev"; then
kdump_setup_vlan "$_dev"
else
_mac=$(kdump_get_mac_addr $_dev)
_kdumpdev=$(kdump_setup_ifname $_dev)
echo -n " ifname=$_kdumpdev:$_mac" >> ${initdir}/etc/cmdline.d/41bridge.conf
fi
_brif+="$_kdumpdev,"
done
echo " bridge=$_netdev:$(echo $_brif | sed -e 's/,$//')" >> ${initdir}/etc/cmdline.d/41bridge.conf
}

kdump_setup_bond() {
local _netdev=$1
local _dev _mac _slaves _kdumpdev
for _dev in `cat /sys/class/net/$_netdev/bonding/slaves`; do
_mac=$(kdump_get_perm_addr $_dev)
_kdumpdev=$(kdump_setup_ifname $_dev)
echo -n " ifname=$_kdumpdev:$_mac" >> ${initdir}/etc/cmdline.d/42bond.conf
_slaves+="$_kdumpdev,"
done
echo -n " bond=$_netdev:$(echo $_slaves | sed 's/,$//')" >> ${initdir}/etc/cmdline.d/42bond.conf
# Get bond options specified in ifcfg

source_ifcfg_file $_netdev

bondoptions="$(echo :$BONDING_OPTS | sed 's/\s\+/,/')"
echo "$bondoptions" >> ${initdir}/etc/cmdline.d/42bond.conf
}

kdump_setup_team() {
local _netdev=$1
local _dev _mac _slaves _kdumpdev
for _dev in `teamnl $_netdev ports | awk -F':' '{print $2}'`; do
_mac=$(kdump_get_perm_addr $_dev)
_kdumpdev=$(kdump_setup_ifname $_dev)
echo -n " ifname=$_kdumpdev:$_mac" >> ${initdir}/etc/cmdline.d/44team.conf
_slaves+="$_kdumpdev,"
done
echo " team=$_netdev:$(echo $_slaves | sed -e 's/,$//')" >> ${initdir}/etc/cmdline.d/44team.conf
#Buggy version teamdctl outputs to stderr!
#Try to use the latest version of teamd.
teamdctl "$_netdev" config dump > ${initdir}/tmp/$$-$_netdev.conf
if [ $? -ne 0 ]
then
derror "teamdctl failed."
exit 1
fi
inst_dir /etc/teamd
inst_simple ${initdir}/tmp/$$-$_netdev.conf "/etc/teamd/$_netdev.conf"
rm -f ${initdir}/tmp/$$-$_netdev.conf
}

kdump_setup_vlan() {
local _netdev=$1
local _phydev="$(awk '/^Device:/{print $2}' /proc/net/vlan/"$_netdev")"
local _netmac="$(kdump_get_mac_addr $_phydev)"
local _kdumpdev

#Just support vlan over bond, it is not easy
#to support all other complex setup
if kdump_is_bridge "$_phydev"; then
derror "Vlan over bridge is not supported!"
exit 1
elif kdump_is_team "$_phydev"; then
derror "Vlan over team is not supported!"
exit 1
elif kdump_is_bond "$_phydev"; then
kdump_setup_bond "$_phydev"
echo " vlan=$_netdev:$_phydev" > ${initdir}/etc/cmdline.d/43vlan.conf
else
_kdumpdev="$(kdump_setup_ifname $_phydev)"
echo " vlan=$_netdev:$_kdumpdev ifname=$_kdumpdev:$_netmac" > ${initdir}/etc/cmdline.d/43vlan.conf
fi
}

# setup s390 znet cmdline
# $1: netdev name
kdump_setup_znet() {
local _options=""

source_ifcfg_file $1

for i in $OPTIONS; do
_options=${_options},$i
done
echo rd.znet=${NETTYPE},${SUBCHANNELS}${_options} > ${initdir}/etc/cmdline.d/30znet.conf
}

# Setup dracut to bringup a given network interface
kdump_setup_netdev() {
local _netdev=$1 _srcaddr=$2
local _static _proto _ip_conf _ip_opts _ifname_opts

if [ "$(uname -m)" = "s390x" ]; then
kdump_setup_znet $_netdev
fi

_netmac=$(kdump_get_mac_addr $_netdev)
_static=$(kdump_static_ip $_netdev $_srcaddr)
if [ -n "$_static" ]; then
_proto=none
elif is_ipv6_address $_srcaddr; then
_proto=either6
else
_proto=dhcp
fi

_ip_conf="${initdir}/etc/cmdline.d/40ip.conf"
_ip_opts=" ip=${_static}$(kdump_setup_ifname $_netdev):${_proto}"

# dracut doesn't allow duplicated configuration for same NIC, even they're exactly the same.
# so we have to avoid adding duplicates
# We should also check /proc/cmdline for existing ip=xx arg.
# For example, iscsi boot will specify ip=xxx arg in cmdline.
if [ ! -f $_ip_conf ] || ! grep -q $_ip_opts $_ip_conf &&\
! grep -q "ip=[^[:space:]]*$_netdev" /proc/cmdline; then
echo "$_ip_opts" >> $_ip_conf
fi

if kdump_is_bridge "$_netdev"; then
kdump_setup_bridge "$_netdev"
elif kdump_is_bond "$_netdev"; then
kdump_setup_bond "$_netdev"
elif kdump_is_team "$_netdev"; then
kdump_setup_team "$_netdev"
elif kdump_is_vlan "$_netdev"; then
kdump_setup_vlan "$_netdev"
else
_ifname_opts=" ifname=$(kdump_setup_ifname $_netdev):$(kdump_get_mac_addr $_netdev)"
echo "$_ifname_opts" >> $_ip_conf
fi

kdump_setup_dns "$_netdev"
}

get_ip_route_field()
{
if `echo $1 | grep -q $2`; then
echo ${1##*$2} | cut -d ' ' -f1
fi
}

#Function:kdump_install_net
#$1: config values of net line in kdump.conf
#$2: srcaddr of network device
kdump_install_net() {
local _server _netdev _srcaddr _route _serv_tmp
local config_val="$1"

_server=$(get_remote_host $config_val)

if is_hostname $_server; then
_serv_tmp=`getent ahosts $_server | grep -v : | head -n 1`
if [ -z "$_serv_tmp" ]; then
_serv_tmp=`getent ahosts $_server | head -n 1`
fi
_server=`echo $_serv_tmp | cut -d' ' -f1`
fi

_route=`/sbin/ip -o route get to $_server 2>&1`
[ $? != 0 ] && echo "Bad kdump location: $config_val" && exit 1

#the field in the ip output changes if we go to another subnet
_srcaddr=$(get_ip_route_field "$_route" "src")
_netdev=$(get_ip_route_field "$_route" "dev")

kdump_setup_netdev "${_netdev}" "${_srcaddr}"

#save netdev used for kdump as cmdline
# Whoever calling kdump_install_net() is setting up the default gateway,
# ie. bootdev/kdumpnic. So don't override the setting if calling
# kdump_install_net() for another time. For example, after setting eth0 as
# the default gate way for network dump, eth1 in the fence kdump path will
# call kdump_install_net again and we don't want eth1 to be the default
# gateway.
if [ ! -f ${initdir}/etc/cmdline.d/60kdumpnic.conf ] &&
[ ! -f ${initdir}/etc/cmdline.d/70bootdev.conf ]; then
echo "kdumpnic=$(kdump_setup_ifname $_netdev)" > ${initdir}/etc/cmdline.d/60kdumpnic.conf
echo "bootdev=$(kdump_setup_ifname $_netdev)" > ${initdir}/etc/cmdline.d/70bootdev.conf
fi
}

default_dump_target_install_conf()
{
local _target _fstype
local _mntpoint _save_path

is_user_configured_dump_target && return

_save_path=$(get_option_value "path")
[ -z "$_save_path" ] && _save_path=$DEFAULT_PATH

# strip the duplicated "/"
_save_path=$(echo $_save_path | tr -s /)

_mntpoint=$(get_mntpoint_from_path $_save_path)
_target=$(get_target_from_path $_save_path)

if is_atomic && is_bind_mount $_mntpoint; then
_save_path=${_save_path##"$_mntpoint"}
# the real dump path in the 2nd kernel, if the mount point is bind mounted.
_save_path=$(get_bind_mount_directory $_mntpoint)/$_save_path
_mntpoint=$(get_mntpoint_from_target $_target)

# the absolute path in the 1st kernel
_save_path=$_mntpoint/$_save_path
fi

_fstype=$(get_fs_type_from_target $_target)
if $(is_fs_type_nfs $_fstype); then
kdump_install_net "$_target"
_fstype="nfs"
else
_target=$(kdump_to_udev_name $_target)
fi

echo "$_fstype $_target" >> ${initdir}/tmp/$$-kdump.conf

# strip the duplicated "/"
_save_path=$(echo $_save_path | tr -s /)
# don't touch the path under root mount
if [ "$_mntpoint" != "/" ]; then
_save_path=${_save_path##"$_mntpoint"}
fi

#erase the old path line, then insert the parsed path
sed -i "/^path/d" ${initdir}/tmp/$$-kdump.conf
echo "path $_save_path" >> ${initdir}/tmp/$$-kdump.conf
}

adjust_bind_mount_path()
{
local _target=$1
local _save_path=$(get_option_value "path")
[ -z "$_save_path" ] && _save_path=$DEFAULT_PATH

# strip the duplicated "/"
_save_path=$(echo $_save_path | tr -s /)

local _absolute_save_path=$(get_mntpoint_from_target $_target)/$_save_path
_absolute_save_path=$(echo "$_absolute_save_path" | tr -s /)
local _mntpoint=$(get_mntpoint_from_path $_absolute_save_path)

if is_bind_mount $_mntpoint; then
_save_path=${_absolute_save_path##"$_mntpoint"}
# the real dump path in the 2nd kernel, if the mount point is bind mounted.
_save_path=$(get_bind_mount_directory $_mntpoint)/$_save_path

#erase the old path line, then insert the parsed path
sed -i "/^path/d" ${initdir}/tmp/$$-kdump.conf
echo "path $_save_path" >> ${initdir}/tmp/$$-kdump.conf
fi
}

#install kdump.conf and what user specifies in kdump.conf
kdump_install_conf() {
sed -ne '/^#/!p' /etc/kdump.conf > ${initdir}/tmp/$$-kdump.conf

while read config_opt config_val;
do
# remove inline comments after the end of a directive.
config_val=$(strip_comments $config_val)
case "$config_opt" in
ext[234]|xfs|btrfs|minix|raw)
sed -i -e "s#^$config_opt[[:space:]]\+$config_val#$config_opt $(kdump_to_udev_name $config_val)#" ${initdir}/tmp/$$-kdump.conf
if is_atomic; then
adjust_bind_mount_path "$config_val"
fi
;;
ssh|nfs)
kdump_install_net "$config_val"
;;
dracut_args)
if [[ $(get_dracut_args_fstype "$config_val") = nfs* ]] ; then
kdump_install_net "$(get_dracut_args_target "$config_val")"
fi
;;
kdump_pre|kdump_post|extra_bins)
dracut_install $config_val
;;
core_collector)
dracut_install "${config_val%%[[:blank:]]*}"
;;
esac
done < /etc/kdump.conf

default_dump_target_install_conf

kdump_configure_fence_kdump "${initdir}/tmp/$$-kdump.conf"
inst "${initdir}/tmp/$$-kdump.conf" "/etc/kdump.conf"
rm -f ${initdir}/tmp/$$-kdump.conf
}

# Default sysctl parameters should suffice for kdump kernel.
# Remove custom configurations sysctl.conf & sysctl.d/*
remove_sysctl_conf() {

# As custom configurations like vm.min_free_kbytes can lead
# to OOM issues in kdump kernel, avoid them
rm -f "${initdir}/etc/sysctl.conf"
rm -rf "${initdir}/etc/sysctl.d"
rm -rf "${initdir}/run/sysctl.d"
rm -rf "${initdir}/usr/lib/sysctl.d"
}

kdump_iscsi_get_rec_val() {

local result

# The open-iscsi 742 release changed to using flat files in
# /var/lib/iscsi.

result=$(/sbin/iscsiadm --show -m session -r ${1} | grep "^${2} = ")
result=${result##* = }
echo $result
}

kdump_get_iscsi_initiator() {
local _initiator
local initiator_conf="/etc/iscsi/initiatorname.iscsi"

[ -f "$initiator_conf" ] || return 1

while read _initiator; do
[ -z "${_initiator%%#*}" ] && continue # Skip comment lines

case $_initiator in
InitiatorName=*)
initiator=${_initiator#InitiatorName=}
echo "rd.iscsi.initiator=${initiator}"
return 0;;
*) ;;
esac
done < ${initiator_conf}

return 1
}

# Figure out iBFT session according to session type
is_ibft() {
[ "$(kdump_iscsi_get_rec_val $1 "node.discovery_type")" = fw ]
}

kdump_setup_iscsi_device() {
local path=$1
local tgt_name; local tgt_ipaddr;
local username; local password; local userpwd_str;
local username_in; local password_in; local userpwd_in_str;
local netdev
local srcaddr
local idev
local netroot_str ; local initiator_str;
local netroot_conf="${initdir}/etc/cmdline.d/50iscsi.conf"
local initiator_conf="/etc/iscsi/initiatorname.iscsi"

dinfo "Found iscsi component $1"

# Check once before getting explicit values, so we can bail out early,
# e.g. in case of pure-hardware(all-offload) iscsi.
if ! /sbin/iscsiadm -m session -r ${path} &>/dev/null ; then
return 1
fi

if is_ibft ${path}; then
return
fi

tgt_name=$(kdump_iscsi_get_rec_val ${path} "node.name")
tgt_ipaddr=$(kdump_iscsi_get_rec_val ${path} "node.conn\[0\].address")

# get and set username and password details
username=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.username")
[ "$username" == "<empty>" ] && username=""
password=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.password")
[ "$password" == "<empty>" ] && password=""
username_in=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.username_in")
[ -n "$username" ] && userpwd_str="$username:$password"

# get and set incoming username and password details
[ "$username_in" == "<empty>" ] && username_in=""
password_in=$(kdump_iscsi_get_rec_val ${path} "node.session.auth.password_in")
[ "$password_in" == "<empty>" ] && password_in=""

[ -n "$username_in" ] && userpwd_in_str=":$username_in:$password_in"

netdev=$(/sbin/ip route get to ${tgt_ipaddr} | \
sed 's|.*dev \(.*\).*|\1|g')
srcaddr=$(echo $netdev | awk '{ print $3; exit }')
netdev=$(echo $netdev | awk '{ print $1; exit }')

kdump_setup_netdev $netdev $srcaddr

# prepare netroot= command line
# FIXME: Do we need to parse and set other parameters like protocol, port
# iscsi_iface_name, netdev_name, LUN etc.

if is_ipv6_address $tgt_ipaddr; then
tgt_ipaddr="[$tgt_ipaddr]"
fi
netroot_str="netroot=iscsi:${userpwd_str}${userpwd_in_str}@$tgt_ipaddr::::$tgt_name"

[[ -f $netroot_conf ]] || touch $netroot_conf

# If netroot target does not exist already, append.
if ! grep -q $netroot_str $netroot_conf; then
echo $netroot_str >> $netroot_conf
dinfo "Appended $netroot_str to $netroot_conf"
fi

# Setup initator
initiator_str=$(kdump_get_iscsi_initiator)
[ $? -ne "0" ] && derror "Failed to get initiator name" && return 1

# If initiator details do not exist already, append.
if ! grep -q "$initiator_str" $netroot_conf; then
echo "$initiator_str" >> $netroot_conf
dinfo "Appended "$initiator_str" to $netroot_conf"
fi
}

kdump_check_iscsi_targets () {
# If our prerequisites are not met, fail anyways.
type -P iscsistart >/dev/null || return 1

kdump_check_setup_iscsi() (
local _dev
_dev=$1

[[ -L /sys/dev/block/$_dev ]] || return
cd "$(readlink -f /sys/dev/block/$_dev)"
until [[ -d sys || -d iscsi_session ]]; do
cd ..
done
[[ -d iscsi_session ]] && kdump_setup_iscsi_device "$PWD"
)

[[ $hostonly ]] || [[ $mount_needs ]] && {
for_each_host_dev_and_slaves_all kdump_check_setup_iscsi
}
}

# retrieves fence_kdump nodes from Pacemaker cluster configuration
get_pcs_fence_kdump_nodes() {
local nodes

# get cluster nodes from cluster cib, get interface and ip address
nodelist=`pcs cluster cib | xmllint --xpath "/cib/status/node_state/@uname" -`

# nodelist is formed as 'uname="node1" uname="node2" ... uname="nodeX"'
# we need to convert each to node1, node2 ... nodeX in each iteration
for node in ${nodelist}; do
# convert $node from 'uname="nodeX"' to 'nodeX'
eval $node
nodename=$uname
# Skip its own node name
if [ "$nodename" = `hostname` -o "$nodename" = `hostname -s` ]; then
continue
fi
nodes="$nodes $nodename"
done

echo $nodes
}

# retrieves fence_kdump args from config file
get_pcs_fence_kdump_args() {
if [ -f $FENCE_KDUMP_CONFIG_FILE ]; then
. $FENCE_KDUMP_CONFIG_FILE
echo $FENCE_KDUMP_OPTS
fi
}

# setup fence_kdump in cluster
# setup proper network and install needed files
kdump_configure_fence_kdump () {
local kdump_cfg_file=$1
local nodes
local args

if is_generic_fence_kdump; then
nodes=$(get_option_value "fence_kdump_nodes")

elif is_pcs_fence_kdump; then
nodes=$(get_pcs_fence_kdump_nodes)

# set appropriate options in kdump.conf
echo "fence_kdump_nodes $nodes" >> ${kdump_cfg_file}

args=$(get_pcs_fence_kdump_args)
if [ -n "$args" ]; then
echo "fence_kdump_args $args" >> ${kdump_cfg_file}
fi

else
# fence_kdump not configured
return 1
fi

# setup network for each node
for node in ${nodes}; do
kdump_install_net $node
done

dracut_install /etc/hosts
dracut_install /etc/nsswitch.conf
dracut_install $FENCE_KDUMP_SEND
}

# Install a random seed used to feed /dev/urandom
# By the time kdump service starts, /dev/uramdom is already fed by systemd
kdump_install_random_seed() {
local poolsize=`cat /proc/sys/kernel/random/poolsize`

if [ ! -d ${initdir}/var/lib/ ]; then
mkdir -p ${initdir}/var/lib/
fi

dd if=/dev/urandom of=${initdir}/var/lib/random-seed \
bs=$poolsize count=1 2> /dev/null
}

remove_cpu_online_rule() {
local file=${initdir}/usr/lib/udev/rules.d/40-redhat.rules

sed -i '/SUBSYSTEM=="cpu"/d' $file
}

install() {
local arch

kdump_install_conf
remove_sysctl_conf

# Onlining secondary cpus breaks kdump completely on KVM on Power hosts
# Though we use maxcpus=1 by default but 40-redhat.rules will bring up all
# possible cpus by default. (rhbz1270174 rhbz1266322)
# Thus before we get the kernel fix and the systemd rule fix let's remove
# the cpu online rule in kdump initramfs.
arch=$(uname -m)
if [[ "$arch" = "ppc64le" ]] || [[ "$arch" = "ppc64" ]]; then
remove_cpu_online_rule
fi

if is_ssh_dump_target; then
kdump_install_random_seed
fi
dracut_install -o /etc/adjtime /etc/localtime
inst "$moddir/monitor_dd_progress" "/kdumpscripts/monitor_dd_progress"
chmod +x ${initdir}/kdumpscripts/monitor_dd_progress
inst "/bin/grep" "/bin/grep"
inst "/bin/cat" "/bin/cat"
inst "/bin/rm" "/bin/rm"
inst "/bin/dd" "/bin/dd"
inst "/bin/tail" "/bin/tail"
inst "/bin/date" "/bin/date"
inst "/bin/sync" "/bin/sync"
inst "/bin/cut" "/bin/cut"
inst "/bin/head" "/bin/head"
inst "/sbin/makedumpfile" "/sbin/makedumpfile"
inst "/sbin/vmcore-dmesg" "/sbin/vmcore-dmesg"
inst "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh"
inst "/lib/kdump/kdump-lib-initramfs.sh" "/lib/kdump-lib-initramfs.sh"
inst "$moddir/kdump.sh" "/usr/bin/kdump.sh"
inst "$moddir/kdump-capture.service" "$systemdsystemunitdir/kdump-capture.service"
ln_r "$systemdsystemunitdir/kdump-capture.service" "$systemdsystemunitdir/initrd.target.wants/kdump-capture.service"
inst "$moddir/kdump-error-handler.sh" "/usr/bin/kdump-error-handler.sh"
inst "$moddir/kdump-error-handler.service" "$systemdsystemunitdir/kdump-error-handler.service"
# Replace existing emergency service and emergency target
cp "$moddir/kdump-emergency.service" "$initdir/$systemdsystemunitdir/emergency.service"
cp "$moddir/kdump-emergency.target" "$initdir/$systemdsystemunitdir/emergency.target"
# Also redirect dracut-emergency to kdump error handler
ln_r "$systemdsystemunitdir/emergency.service" "$systemdsystemunitdir/dracut-emergency.service"

# Check for all the devices and if any device is iscsi, bring up iscsi
# target. Ideally all this should be pushed into dracut iscsi module
# at some point of time.
kdump_check_iscsi_targets

# For the lvm type target under kdump, in /etc/lvm/lvm.conf we can
# safely replace "reserved_memory=XXXX"(default value is 8192) with
# "reserved_memory=1024" to lower memory pressure under kdump. We do
# it unconditionally here, if "/etc/lvm/lvm.conf" doesn't exist, it
# actually does nothing.
sed -i -e \
's/\(^[[:space:]]*reserved_memory[[:space:]]*=\)[[:space:]]*[[:digit:]]*/\1 1024/' \
${initdir}/etc/lvm/lvm.conf &>/dev/null

# Kdump turns out to require longer default systemd mount timeout
# than 1st kernel(90s by default), we use default 300s for kdump.
grep -r "^[[:space:]]*DefaultTimeoutStartSec=" ${initdir}/etc/systemd/system.conf* &>/dev/null
if [ $? -ne 0 ]; then
mkdir -p ${initdir}/etc/systemd/system.conf.d
echo "[Manager]" > ${initdir}/etc/systemd/system.conf.d/kdump.conf
echo "DefaultTimeoutStartSec=300s" >> ${initdir}/etc/systemd/system.conf.d/kdump.conf
fi
}

28
SOURCES/dracut-monitor_dd_progress

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
#!/bin/sh

SRC_FILE_MB=$1

while true
do
DD_PID=`pidof dd`
if [ -n "$DD_PID" ]; then
break
fi
done

while true
do
sleep 5
if [ ! -d /proc/$DD_PID ]; then
break
fi

kill -s USR1 $DD_PID
CURRENT_SIZE=`tail -n 1 /tmp/dd_progress_file | sed "s/[^0-9].*//g"`
[ -n "$CURRENT_SIZE" ] && {
CURRENT_MB=$(($CURRENT_SIZE / 1048576))
echo -e "Copied $CURRENT_MB MB / $SRC_FILE_MB MB\r"
}
done

rm -f /tmp/dd_progress_file

251
SOURCES/fadump-howto.txt

@ -0,0 +1,251 @@ @@ -0,0 +1,251 @@
Firmware assisted dump (fadump) HOWTO

Introduction

Firmware assisted dump is a new feature in the 3.4 mainline kernel supported
only on powerpc architecture. The goal of firmware-assisted dump is to enable
the dump of a crashed system, and to do so from a fully-reset system, and to
minimize the total elapsed time until the system is back in production use. A
complete documentation on implementation can be found at
Documentation/powerpc/firmware-assisted-dump.txt in upstream linux kernel tree
from 3.4 version and above.

Please note that the firmware-assisted dump feature is only available on Power6
and above systems with recent firmware versions.

Overview

Fadump

Fadump is a robust kernel crash dumping mechanism to get reliable kernel crash
dump with assistance from firmware. This approach does not use kexec, instead
firmware assists in booting the kdump kernel while preserving memory contents.
Unlike kdump, the system is fully reset, and loaded with a fresh copy of the
kernel. In particular, PCI and I/O devices are reinitialized and are in a
clean, consistent state. This second kernel, often called a capture kernel,
boots with very little memory and captures the dump image.

The first kernel registers the sections of memory with the Power firmware for
dump preservation during OS initialization. These registered sections of memory
are reserved by the first kernel during early boot. When a system crashes, the
Power firmware fully resets the system, preserves all the system memory
contents, save the low memory (boot memory of size larger of 5% of system
RAM or 256MB) of RAM to the previous registered region. It will also save
system registers, and hardware PTE's.

Fadump is supported only on ppc64 platform. The standard kernel and capture
kernel are one and the same on ppc64.

If you're reading this document, you should already have kexec-tools
installed. If not, you install it via the following command:

# yum install kexec-tools

Fadump Operational Flow:

Like kdump, fadump also exports the ELF formatted kernel crash dump through
/proc/vmcore. Hence existing kdump infrastructure can be used to capture fadump
vmcore. The idea is to keep the functionality transparent to end user. From
user perspective there is no change in the way kdump init script works.

However, unlike kdump, fadump does not pre-load kdump kernel and initrd into
reserved memory, instead it always uses default OS initrd during second boot
after crash. Hence, for fadump, we rebuild the new kdump initrd and replace it
with default initrd. Before replacing existing default initrd we take a backup
of original default initrd for user's reference. The dracut package has been
enhanced to rebuild the default initrd with vmcore capture steps. The initrd
image is rebuilt as per the configuration in /etc/kdump.conf file.

The control flow of fadump works as follows:
01. System panics.
02. At the crash, kernel informs power firmware that kernel has crashed.
03. Firmware takes the control and reboots the entire system preserving
only the memory (resets all other devices).
04. The reboot follows the normal booting process (non-kexec).
05. The boot loader loads the default kernel and initrd from /boot
06. The default initrd loads and runs /init
07. dracut-kdump.sh script present in fadump aware default initrd checks if
'/proc/device-tree/rtas/ibm,kernel-dump' file exists before executing
steps to capture vmcore.
(This check will help to bypass the vmcore capture steps during normal boot
process.)
09. Captures dump according to /etc/kdump.conf
10. Is dump capture successful (yes goto 12, no goto 11)
11. Perfom the default action specified in /etc/kdump.conf (Default action
is reboot, if unspecified)
12. Reboot


How to configure fadump:

Again, we assume if you're reading this document, you should already have
kexec-tools installed. If not, you install it via the following command:

# yum install kexec-tools

To be able to do much of anything interesting in the way of debug analysis,
you'll also need to install the kernel-debuginfo package, of the same arch
as your running kernel, and the crash utility:

# yum --enablerepo=\*debuginfo install kernel-debuginfo.$(uname -m) crash

Next up, we need to modify some boot parameters to enable firmware assisted
dump. With the help of grubby, it's very easy to append "fadump=on" to the end
of your kernel boot parameters. Optionally, user can also append
'fadump_reserve_mem=X' kernel cmdline to specify size of the memory to reserve
for boot memory dump preservation.

# grubby --args="fadump=on" --update-kernel=/boot/vmlinuz-`uname -r`

The term 'boot memory' means size of the low memory chunk that is required for
a kernel to boot successfully when booted with restricted memory. By default,
the boot memory size will be the larger of 5% of system RAM or 256MB.
Alternatively, user can also specify boot memory size through boot parameter
'fadump_reserve_mem=' which will override the default calculated size. Use this
option if default boot memory size is not sufficient for second kernel to boot
successfully.

After making said changes, reboot your system, so that the specified memory is
reserved and left untouched by the normal system. Take note that the output of
'free -m' will show X MB less memory than without this parameter, which is
expected. If you see OOM (Out Of Memory) error messages while loading capture
kernel, then you should bump up the memory reservation size.

Now that you've got that reserved memory region set up, you want to turn on
the kdump init script:

# systemctl enable kdump.service

Then, start up kdump as well:

# systemctl start kdump.service

This should turn on the firmware assisted functionality in kernel by
echo'ing 1 to /sys/kernel/fadump_registered, leaving the system ready
to capture a vmcore upon crashing. To test this out, you can force-crash
your system by echo'ing a c into /proc/sysrq-trigger:

# echo c > /proc/sysrq-trigger

You should see some panic output, followed by the system reset and booting into
fresh copy of kernel. When default initrd loads and runs /init, vmcore should
be copied out to disk (by default, in /var/crash/<YYYY.MM.DD-HH:MM:SS>/vmcore),
then the system rebooted back into your normal kernel.

Once back to your normal kernel, you can use the previously installed crash
kernel in conjunction with the previously installed kernel-debuginfo to
perform postmortem analysis:

# crash /usr/lib/debug/lib/modules/2.6.17-1.2621.el5/vmlinux
/var/crash/2006-08-23-15:34/vmcore

crash> bt

and so on...

Saving vmcore-dmesg.txt
----------------------
Kernel log bufferes are one of the most important information available
in vmcore. Now before saving vmcore, kernel log bufferes are extracted
from /proc/vmcore and saved into a file vmcore-dmesg.txt. After
vmcore-dmesg.txt, vmcore is saved. Destination disk and directory for
vmcore-dmesg.txt is same as vmcore. Note that kernel log buffers will
not be available if dump target is raw device.

Dump Triggering methods:

This section talks about the various ways, other than a Kernel Panic, in which
fadump can be triggered. The following methods assume that fadump is configured
on your system, with the scripts enabled as described in the section above.

1) AltSysRq C

FAdump can be triggered with the combination of the 'Alt','SysRq' and 'C'
keyboard keys. Please refer to the following link for more details:

https://access.redhat.com/articles/231663

In addition, on PowerPC boxes, fadump can also be triggered via Hardware
Management Console(HMC) using 'Ctrl', 'O' and 'C' keyboard keys.

2) Kernel OOPs

If we want to generate a dump everytime the Kernel OOPses, we can achieve this
by setting the 'Panic On OOPs' option as follows:

# echo 1 > /proc/sys/kernel/panic_on_oops

3) PowerPC specific methods:

On IBM PowerPC machines, issuing a soft reset invokes the XMON debugger(if
XMON is configured). To configure XMON one needs to compile the kernel with
the CONFIG_XMON and CONFIG_XMON_DEFAULT options, or by compiling with
CONFIG_XMON and booting the kernel with xmon=on option.

Following are the ways to remotely issue a soft reset on PowerPC boxes, which
would drop you to XMON. Pressing a 'X' (capital alphabet X) followed by an
'Enter' here will trigger the dump.

3.1) HMC

Hardware Management Console(HMC) available on Power4 and Power5 machines allow
partitions to be reset remotely. This is specially useful in hang situations
where the system is not accepting any keyboard inputs.

Once you have HMC configured, the following steps will enable you to trigger
fadump via a soft reset:

On Power4
Using GUI

* In the right pane, right click on the partition you wish to dump.
* Select "Operating System->Reset".
* Select "Soft Reset".
* Select "Yes".

Using HMC Commandline

# reset_partition -m <machine> -p <partition> -t soft

On Power5
Using GUI

* In the right pane, right click on the partition you wish to dump.
* Select "Restart Partition".
* Select "Dump".
* Select "OK".

Using HMC Commandline

# chsysstate -m <managed system name> -n <lpar name> -o dumprestart -r lpar

3.2) Blade Management Console for Blade Center

To initiate a dump operation, go to Power/Restart option under "Blade Tasks" in
the Blade Management Console. Select the corresponding blade for which you want
to initate the dump and then click "Restart blade with NMI". This issues a
system reset and invokes xmon debugger.


Advanced Setups & Default action:

Kdump and fadump exhibit similar behavior in terms of setup & default action.
For fadump advanced setup related information see section "Advanced Setups" in
"kexec-kdump-howto.txt" document. Refer to "Default action" section in "kexec-
kdump-howto.txt" document for fadump default action related information.

Compression and filtering

Refer "Compression and filtering" section in "kexec-kdump-howto.txt" document.
Compression and filtering are same for kdump & fadump.


Notes on rootfs mount:
Dracut is designed to mount rootfs by default. If rootfs mounting fails it
will refuse to go on. So fadump leaves rootfs mounting to dracut currently.
We make the assumtion that proper root= cmdline is being passed to dracut
initramfs for the time being. If you need modify "KDUMP_COMMANDLINE=" in
/etc/sysconfig/kdump, you will need to make sure that appropriate root=
options are copied from /proc/cmdline. In general it is best to append
command line options using "KDUMP_COMMANDLINE_APPEND=" instead of replacing
the original command line completely.

22
SOURCES/kdump-dep-generator.sh

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
#!/bin/sh

# More details about systemd generator:
# http://www.freedesktop.org/wiki/Software/systemd/Generators/

. /usr/lib/kdump/kdump-lib.sh

# If invokded with no arguments for testing purpose, output to /tmp to
# avoid overriding the existing.
dest_dir="/tmp"

if [ -n "$1" ]; then
dest_dir=$1
fi

systemd_dir=/usr/lib/systemd/system
kdump_wants=$dest_dir/kdump.service.wants

if is_ssh_dump_target; then
mkdir -p $kdump_wants
ln -sf $systemd_dir/network-online.target $kdump_wants/
fi

91
SOURCES/kdump-in-cluster-environment.txt

@ -0,0 +1,91 @@ @@ -0,0 +1,91 @@
Kdump-in-cluster-environment HOWTO

Introduction

Kdump is a kexec based crash dumping mechansim for Linux. This docuement
illustrate how to configure kdump in cluster environment to allow the kdump
crash recovery service complete without being preempted by traditional power
fencing methods.

Overview

Kexec/Kdump

Details about Kexec/Kdump are available in Kexec-Kdump-howto file and will not
be described here.

fence_kdump

fence_kdump is an I/O fencing agent to be used with the kdump crash recovery
service. When the fence_kdump agent is invoked, it will listen for a message
from the failed node that acknowledges that the failed node is executing the
kdump crash kernel. Note that fence_kdump is not a replacement for traditional
fencing methods. The fence_kdump agent can only detect that a node has entered
the kdump crash recovery service. This allows the kdump crash recovery service
complete without being preempted by traditional power fencing methods.

fence_kdump_send

fence_kdump_send is a utility used to send messages that acknowledge that the
node itself has entered the kdump crash recovery service. The fence_kdump_send
utility is typically run in the kdump kernel after a cluster node has
encountered a kernel panic. Once the cluster node has entered the kdump crash
recovery service, fence_kdump_send will periodically send messages to all
cluster nodes. When the fence_kdump agent receives a valid message from the
failed nodes, fencing is complete.

How to configure Pacemaker cluster environment:

If we want to use kdump in Pacemaker cluster environment, fence-agents-kdump
should be installed in every nodes in the cluster. You can achieve this via
the following command:

# yum install -y fence-agents-kdump

Next is to add kdump_fence to the cluster. Assuming that the cluster consists
of three nodes, they are node1, node2 and node3, and use Pacemaker to perform
resource management and pcs as cli configuration tool.

With pcs it is easy to add a stonith resource to the cluster. For example, add
a stonith resource named mykdumpfence with fence type of fence_kdump via the
following commands:
# pcs stonith create mykdumpfence fence_kdump \
pcmk_host_check=static-list pcmk_host_list="node1 node2 node3"
# pcs stonith update mykdumpfence pcmk_monitor_action=metadata --force
# pcs stonith update mykdumpfence pcmk_status_action=metadata --force
# pcs stonith update mykdumpfence pcmk_reboot_action=off --force
Then enable stonith
# pcs property set stonith-enabled=true

How to configure kdump:

Actually there are two ways how to configure fence_kdump support:

1) Pacemaker based clusters
If you have successfully configured fence_kdump in Pacemaker, there is
no need to add some special configuration in kdump. So please refer to
Kexec-Kdump-howto file for more information.

2) Generic clusters
For other types of clusters there are two configuration options in
kdump.conf which enables fence_kdump support:

fence_kdump_nodes <node(s)>
Contains list of cluster node(s) separated by space to send
fence_kdump notification to (this option is mandatory to enable
fence_kdump)

fence_kdump_args <arg(s)>
Command line arguments for fence_kdump_send (it can contain
all valid arguments except hosts to send notification to)

These options will most probably be configured by your cluster software,
so please refer to your cluster documentation how to enable fence_kdump
support.

Please be aware that these two ways cannot be combined and 2) has precedence
over 1). It means that if fence_kdump is configured using fence_kdump_nodes
and fence_kdump_args options in kdump.conf, Pacemaker configuration is not
used even if it exists.

165
SOURCES/kdump-lib-initramfs.sh

@ -0,0 +1,165 @@ @@ -0,0 +1,165 @@
# These variables and functions are useful in 2nd kernel

. /lib/kdump-lib.sh

KDUMP_PATH="/var/crash"
CORE_COLLECTOR=""
DEFAULT_CORE_COLLECTOR="makedumpfile -l --message-level 1 -d 31"
DMESG_COLLECTOR="/sbin/vmcore-dmesg"
DEFAULT_ACTION="systemctl reboot -f"
DATEDIR=`date +%Y-%m-%d-%T`
HOST_IP='127.0.0.1'
DUMP_INSTRUCTION=""
SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa"
KDUMP_SCRIPT_DIR="/kdumpscripts"
DD_BLKSIZE=512
FINAL_ACTION="systemctl reboot -f"
KDUMP_CONF="/etc/kdump.conf"
KDUMP_PRE=""
KDUMP_POST=""
NEWROOT="/sysroot"

get_kdump_confs()
{
local config_opt config_val

while read config_opt config_val;
do
# remove inline comments after the end of a directive.
config_val=$(strip_comments $config_val)
case "$config_opt" in
path)
KDUMP_PATH="$config_val"
;;
core_collector)
[ -n "$config_val" ] && CORE_COLLECTOR="$config_val"
;;
sshkey)
if [ -f "$config_val" ]; then
SSH_KEY_LOCATION=$config_val
fi
;;
kdump_pre)
KDUMP_PRE="$config_val"
;;
kdump_post)
KDUMP_POST="$config_val"
;;
fence_kdump_args)
FENCE_KDUMP_ARGS="$config_val"
;;
fence_kdump_nodes)
FENCE_KDUMP_NODES="$config_val"
;;
default)
case $config_val in
shell)
DEFAULT_ACTION="kdump_emergency_shell"
;;
reboot)
DEFAULT_ACTION="systemctl reboot -f"
;;
halt)
DEFAULT_ACTION="halt"
;;
poweroff)
DEFAULT_ACTION="poweroff"
;;
dump_to_rootfs)
DEFAULT_ACTION="dump_to_rootfs"
;;
esac
;;
esac
done < $KDUMP_CONF

if [ -z "$CORE_COLLECTOR" ]; then
CORE_COLLECTOR="$DEFAULT_CORE_COLLECTOR"
if is_ssh_dump_target || is_raw_dump_target; then
CORE_COLLECTOR="$CORE_COLLECTOR -F"
fi
fi
}

# dump_fs <mount point| device>
dump_fs()
{

local _dev=$(findmnt -k -f -n -r -o SOURCE $1)
local _mp=$(findmnt -k -f -n -r -o TARGET $1)

echo "kdump: dump target is $_dev"

if [ -z "$_mp" ]; then
echo "kdump: error: Dump target $_dev is not mounted."
return 1
fi

# Remove -F in makedumpfile case. We don't want a flat format dump here.
[[ $CORE_COLLECTOR = *makedumpfile* ]] && CORE_COLLECTOR=`echo $CORE_COLLECTOR | sed -e "s/-F//g"`

echo "kdump: saving to $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/"

mount -o remount,rw $_mp || return 1
mkdir -p $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR || return 1

save_vmcore_dmesg_fs ${DMESG_COLLECTOR} "$_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/"

echo "kdump: saving vmcore"
$CORE_COLLECTOR /proc/vmcore $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore-incomplete || return 1
mv $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore-incomplete $_mp/$KDUMP_PATH/$HOST_IP-$DATEDIR/vmcore
sync

echo "kdump: saving vmcore complete"
# improper kernel cmdline can cause the failure of echo, we can ignore this kind of failure
return 0
}

save_vmcore_dmesg_fs() {
local _dmesg_collector=$1
local _path=$2

echo "kdump: saving vmcore-dmesg.txt"
$_dmesg_collector /proc/vmcore > ${_path}/vmcore-dmesg-incomplete.txt
_exitcode=$?
if [ $_exitcode -eq 0 ]; then
mv ${_path}/vmcore-dmesg-incomplete.txt ${_path}/vmcore-dmesg.txt

# Make sure file is on disk. There have been instances where later
# saving vmcore failed and system rebooted without sync and there
# was no vmcore-dmesg.txt available.
sync
echo "kdump: saving vmcore-dmesg.txt complete"
else
echo "kdump: saving vmcore-dmesg.txt failed"
fi
}

dump_to_rootfs()
{

echo "Kdump: trying to bring up rootfs device"
systemctl start dracut-initqueue
echo "Kdump: waiting for rootfs mount, will timeout after 90 seconds"
systemctl start sysroot.mount

dump_fs $NEWROOT
}

kdump_emergency_shell()
{
echo "PS1=\"kdump:\\\${PWD}# \"" >/etc/profile
/bin/dracut-emergency
rm -f /etc/profile
}

do_default_action()
{
echo "Kdump: Executing default action $DEFAULT_ACTION"
eval $DEFAULT_ACTION
}

do_final_action()
{
eval $FINAL_ACTION
}

520
SOURCES/kdump-lib.sh

@ -0,0 +1,520 @@ @@ -0,0 +1,520 @@
#!/bin/sh
#
# Kdump common variables and functions
#

DEFAULT_PATH="/var/crash/"
FENCE_KDUMP_CONFIG_FILE="/etc/sysconfig/fence_kdump"
FENCE_KDUMP_SEND="/usr/libexec/fence_kdump_send"
FADUMP_ENABLED_SYS_NODE="/sys/kernel/fadump_enabled"

is_fadump_capable()
{
# Check if firmware-assisted dump is enabled
# if no, fallback to kdump check
if [ -f $FADUMP_ENABLED_SYS_NODE ]; then
rc=`cat $FADUMP_ENABLED_SYS_NODE`
[ $rc -eq 1 ] && return 0
fi
return 1
}

perror_exit() {
echo $@ >&2
exit 1
}

perror() {
echo $@ >&2
}

is_ssh_dump_target()
{
grep -q "^ssh[[:blank:]].*@" /etc/kdump.conf
}

is_nfs_dump_target()
{
grep -q "^nfs" /etc/kdump.conf || \
[[ $(get_dracut_args_fstype "$(grep "^dracut_args .*\-\-mount" /etc/kdump.conf)") = nfs* ]]
}

is_raw_dump_target()
{
grep -q "^raw" /etc/kdump.conf
}

is_fs_type_nfs()
{
local _fstype=$1
[ $_fstype = "nfs" ] || [ $_fstype = "nfs4" ] && return 0
return 1
}

is_fs_dump_target()
{
egrep -q "^ext[234]|^xfs|^btrfs|^minix" /etc/kdump.conf
}

strip_comments()
{
echo $@ | sed -e 's/\(.*\)#.*/\1/'
}

# Check if fence kdump is configured in Pacemaker cluster
is_pcs_fence_kdump()
{
# no pcs or fence_kdump_send executables installed?
type -P pcs > /dev/null || return 1
[ -x $FENCE_KDUMP_SEND ] || return 1

# fence kdump not configured?
(pcs cluster cib | grep 'type="fence_kdump"') &> /dev/null || return 1
}

# Check if fence_kdump is configured using kdump options
is_generic_fence_kdump()
{
[ -x $FENCE_KDUMP_SEND ] || return 1

grep -q "^fence_kdump_nodes" /etc/kdump.conf
}

to_dev_name() {
local dev="${1//\"/}"

case "$dev" in
UUID=*)
dev=`blkid -U "${dev#UUID=}"`
;;
LABEL=*)
dev=`blkid -L "${dev#LABEL=}"`
;;
esac
echo $dev
}

kdump_get_persistent_dev() {
local i _tmp _dev _lookup_dirs

_dev=$(udevadm info --query=name --name="$1" 2>/dev/null)
[ -z "$_dev" ] && {
perror_exit "Kernel dev name of $1 is not found."
}

if [[ $2 = "raw" ]];then
_lookup_dirs="/dev/mapper/* /dev/disk/by-id/* /dev/disk/by-path/*"
else
_lookup_dirs="/dev/mapper/* /dev/disk/by-uuid/* /dev/disk/by-id/*"
fi

for i in $_lookup_dirs; do
_tmp=$(udevadm info --query=name --name="$i" 2>/dev/null)
if [ "$_tmp" = "$_dev" ]; then
echo $i
return
fi
done

perror "WARNING: Persistent device name of $1 not found. Using $1 as dump target name"
echo $1
}

is_user_configured_dump_target()
{
return $(is_mount_in_dracut_args || is_ssh_dump_target || is_nfs_dump_target || \
is_raw_dump_target || is_fs_dump_target)
}

get_user_configured_dump_disk()
{
local _target

_target=$(egrep "^ext[234]|^xfs|^btrfs|^minix|^raw" /etc/kdump.conf 2>/dev/null |awk '{print $2}')
[ -n "$_target" ] && echo $_target && return

_target=$(get_dracut_args_target "$(grep "^dracut_args .*\-\-mount" /etc/kdump.conf)")
[ -b "$_target" ] && echo $_target
}

get_root_fs_device()
{
local _target
_target=$(findmnt -k -f -n -o SOURCE /)
[ -n "$_target" ] && echo $_target

return
}

get_save_path()
{
local _save_path=$(grep "^path" /etc/kdump.conf|awk '{print $2}')
if [ -z "$_save_path" ]; then
_save_path=$DEFAULT_PATH
fi

echo $_save_path
}

get_block_dump_target()
{
local _target _path

if is_ssh_dump_target || is_nfs_dump_target; then
return
fi

_target=$(get_user_configured_dump_disk)
[ -n "$_target" ] && echo $(to_dev_name $_target) && return

# Get block device name from local save path
_path=$(get_save_path)
_target=$(get_target_from_path $_path)
[ -b "$_target" ] && echo $(to_dev_name $_target)
}

is_dump_to_rootfs()
{
grep "^default[[:space:]]dump_to_rootfs" /etc/kdump.conf >/dev/null
}

get_default_action_target()
{
local _target

if is_dump_to_rootfs; then
# Get rootfs device name
_target=$(get_root_fs_device)
[ -b "$_target" ] && echo $(to_dev_name $_target) && return
# Then, must be nfs root
echo "nfs"
fi
}

# Get kdump targets(including root in case of dump_to_rootfs).
get_kdump_targets()
{
local _target _root
local kdump_targets

_target=$(get_block_dump_target)
if [ -n "$_target" ]; then
kdump_targets=$_target
elif is_ssh_dump_target; then
kdump_targets="ssh"
else
kdump_targets="nfs"
fi

# Add the root device if dump_to_rootfs is specified.
_root=$(get_default_action_target)
if [ -n "$_root" -a "$kdump_targets" != "$_root" ]; then
kdump_targets="$kdump_targets $_root"
fi

echo "$kdump_targets"
}


# findmnt uses the option "-v, --nofsroot" to exclusive the [/dir]
# in the SOURCE column for bind-mounts, then if $_mntpoint equals to
# $_mntpoint_nofsroot, the mountpoint is not bind mounted directory.
is_bind_mount()
{
local _mntpoint=$(findmnt $1 | tail -n 1 | awk '{print $2}')
local _mntpoint_nofsroot=$(findmnt -v $1 | tail -n 1 | awk '{print $2}')

if [[ $_mntpoint = $_mntpoint_nofsroot ]]; then
return 1
else
return 0
fi
}

# Below is just an example for mount info
# /dev/mapper/atomicos-root[/ostree/deploy/rhel-atomic-host/var], if the
# directory is bind mounted. The former part represents the device path, rest
# part is the bind mounted directory which quotes by bracket "[]".
get_bind_mount_directory()
{
local _mntpoint=$(findmnt $1 | tail -n 1 | awk '{print $2}')
local _mntpoint_nofsroot=$(findmnt -v $1 | tail -n 1 | awk '{print $2}')

_mntpoint=${_mntpoint#*$_mntpoint_nofsroot}

_mntpoint=${_mntpoint#[}
_mntpoint=${_mntpoint%]}

echo $_mntpoint
}

get_mntpoint_from_path()
{
echo $(df $1 | tail -1 | awk '{print $NF}')
}

get_target_from_path()
{
echo $(df $1 | tail -1 | awk '{print $1}')
}

get_fs_type_from_target()
{
echo $(findmnt -k -f -n -r -o FSTYPE $1)
}

# input: device path
# output: the general mount point
# find the general mount point, not the bind mounted point in atomic
# As general system, Use the previous code
#
# ERROR and EXIT:
# the device can be umounted the general mount point, if one of the mount point is bind mounted
# For example:
# mount /dev/sda /mnt/
# mount -o bind /mnt/var /var
# umount /mnt
get_mntpoint_from_target()
{
if is_atomic; then
for _mnt in $(findmnt -k -n -r -o TARGET $1)
do
if ! is_bind_mount $_mnt; then
echo $_mnt
return
fi
done

echo "Mount $1 firstly, without the bind mode" >&2
exit 1
else
echo $(findmnt -k -f -n -r -o TARGET $1)
fi
}

# get_option_value <option_name>
# retrieves value of option defined in kdump.conf
get_option_value() {
echo $(strip_comments `grep ^$1 /etc/kdump.conf | tail -1 | cut -d\ -f2-`)
}

#This function compose a absolute path with the mount
#point and the relative $SAVE_PATH.
#target is passed in as argument, could be UUID, LABEL,
#block device or even nfs server export of the form of
#"my.server.com:/tmp/export"?
#And possibly this could be used for both default case
#as well as when dump taret is specified. When dump
#target is not specified, then $target would be null.
make_absolute_save_path()
{
local _target=$1
local _mnt

[ -n $_target ] && _mnt=$(get_mntpoint_from_target $1)
_mnt="${_mnt}/$SAVE_PATH"

# strip the duplicated "/"
echo "$_mnt" | tr -s /
}

check_save_path_fs()
{
local _path=$1

if [ ! -d $_path ]; then
perror_exit "Dump path $_path does not exist."
fi
}

is_atomic()
{
grep -q "ostree" /proc/cmdline
}

is_ipv6_address()
{
echo $1 | grep -q ":"
}

# get ip address or hostname from nfs/ssh config value
get_remote_host()
{
local _config_val=$1

# ipv6 address in kdump.conf is around with "[]",
# factor out the ipv6 address
_config_val=${_config_val#*@}
_config_val=${_config_val%:/*}
_config_val=${_config_val#[}
_config_val=${_config_val%]}
echo $_config_val
}

is_hostname()
{
local _hostname=`echo $1 | grep ":"`

if [ -n "$_hostname" ]; then
return 1
fi
echo $1 | grep -q "[a-zA-Z]"
}

# Copied from "/etc/sysconfig/network-scripts/network-functions"
get_hwaddr()
{
if [ -f "/sys/class/net/${1}/address" ]; then
awk '{ print toupper($0) }' < /sys/class/net/${1}/address
elif [ -d "/sys/class/net/${1}" ]; then
LC_ALL= LANG= ip -o link show ${1} 2>/dev/null | \
awk '{ print toupper(gensub(/.*link\/[^ ]* ([[:alnum:]:]*).*/,
"\\1", 1)); }'
fi
}

get_ifcfg_by_device()
{
grep -E -i -l "^[[:space:]]*DEVICE=\"*${1}\"*[[:space:]]*$" \
/etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1
}

get_ifcfg_by_hwaddr()
{
grep -E -i -l "^[[:space:]]*HWADDR=\"*${1}\"*[[:space:]]*$" \
/etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1
}

get_ifcfg_by_uuid()
{
grep -E -i -l "^[[:space:]]*UUID=\"*${1}\"*[[:space:]]*$" \
/etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1
}

get_ifcfg_by_name()
{
grep -E -i -l "^[[:space:]]*NAME=\"*${1}\"*[[:space:]]*$" \
/etc/sysconfig/network-scripts/ifcfg-* 2>/dev/null | head -1
}

is_nm_running()
{
[ "$(LANG=C nmcli -t --fields running general status 2>/dev/null)" = "running" ]
}

is_nm_handling()
{
LANG=C nmcli -t --fields device,state dev status 2>/dev/null \
| grep -q "^\(${1}:connected\)\|\(${1}:connecting.*\)$"
}

# $1: netdev name
get_ifcfg_nmcli()
{
local nm_uuid nm_name
local ifcfg_file

# Get the active nmcli config name of $1
if is_nm_running && is_nm_handling "${1}" ; then
# The configuration "uuid" and "name" generated by nm is wrote to
# the ifcfg file as "UUID=<nm_uuid>" and "NAME=<nm_name>".
nm_uuid=$(LANG=C nmcli -t --fields uuid,device c show --active 2>/dev/null \
| grep "${1}" | head -1 | cut -d':' -f1)
nm_name=$(LANG=C nmcli -t --fields name,device c show --active 2>/dev/null \
| grep "${1}" | head -1 | cut -d':' -f1)
ifcfg_file=$(get_ifcfg_by_uuid "${nm_uuid}")
[ -z "${ifcfg_file}" ] && ifcfg_file=$(get_ifcfg_by_name "${nm_name}")
fi

echo -n "${ifcfg_file}"
}

# $1: netdev name
get_ifcfg_legacy()
{
local ifcfg_file

ifcfg_file="/etc/sysconfig/network-scripts/ifcfg-${1}"
[ -f "${ifcfg_file}" ] && echo -n "${ifcfg_file}" && return

ifcfg_file=$(get_ifcfg_by_name "${1}")
[ -f "${ifcfg_file}" ] && echo -n "${ifcfg_file}" && return

local hwaddr=$(get_hwaddr "${1}")
if [ -n "$hwaddr" ]; then
ifcfg_file=$(get_ifcfg_by_hwaddr "${hwaddr}")
[ -f "${ifcfg_file}" ] && echo -n "${ifcfg_file}" && return
fi

ifcfg_file=$(get_ifcfg_by_device "${1}")

echo -n "${ifcfg_file}"
}

# $1: netdev name
# Return the ifcfg file whole name(including the path) of $1 if any.
get_ifcfg_filename() {
local ifcfg_file

ifcfg_file=$(get_ifcfg_nmcli "${1}")
if [ -z "${ifcfg_file}" ]; then
ifcfg_file=$(get_ifcfg_legacy "${1}")
fi

echo -n "${ifcfg_file}"
}

# returns 0 when omission of watchdog module is desired in dracut_args
# returns 1 otherwise
is_wdt_mod_omitted() {
local dracut_args
local ret=1

dracut_args=$(grep "^dracut_args" /etc/kdump.conf)
[[ -z $dracut_args ]] && return $ret

eval set -- $dracut_args
while :; do
[[ -z $1 ]] && break
case $1 in
-o|--omit)
echo $2 | grep -qw "watchdog"
[[ $? == 0 ]] && ret=0
break
esac
shift
done

return $ret
}

# If "dracut_args" contains "--mount" information, use it
# directly without any check(users are expected to ensure
# its correctness).
is_mount_in_dracut_args()
{
grep -q "^dracut_args .*\-\-mount" /etc/kdump.conf
}

# If $1 contains dracut_args "--mount", return <filesystem type>
get_dracut_args_fstype()
{
echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f3
}

# If $1 contains dracut_args "--mount", return <device>
get_dracut_args_target()
{
echo $1 | grep "\-\-mount" | sed "s/.*--mount .\(.*\)/\1/" | cut -d' ' -f1
}

# Get currently loaded modules
# sorted, and delimited by newline
get_loaded_kernel_modules()
{
local modules=( )
while read _module _size _used _used_by; do
modules+=( "$_module" )
done <<< "$(lsmod | sed -n '1!p')"
printf '%s\n' "${modules[@]}" | sort
}

163
SOURCES/kdump.conf

@ -0,0 +1,163 @@ @@ -0,0 +1,163 @@
# This file contains a series of commands to perform (in order) in the kdump
# kernel after a kernel crash in the crash kernel(1st kernel) has happened.
#
# Directives in this file are only applicable to the kdump initramfs, and have
# no effect once the root filesystem is mounted and the normal init scripts are
# processed.
#
# Currently, only one dump target and path can be specified. If the dumping to
# the configured target fails, the default action which can be configured via
# the "default" directive will be performed.
#
# Supported options:
#
# raw <partition>
# - Will dd /proc/vmcore into <partition>.
# Use persistent device names for partition devices,
# such as /dev/vg/<devname>.
#
# nfs <nfs mount>
# - Will mount nfs to <mnt>, and copy /proc/vmcore to
# <mnt>/<path>/%HOST-%DATE/, supports DNS.
#
# ssh <user@server>
# - Will scp /proc/vmcore to <user@server>:<path>/%HOST-%DATE/,
# supports DNS.
# NOTE: make sure the user has write permissions on the server.
#
# sshkey <path>
# - Will use the sshkey to do ssh dump.
# Specify the path of the ssh key to use when dumping
# via ssh. The default value is /root/.ssh/kdump_id_rsa.
#
# <fs type> <partition>
# - Will mount -t <fs type> <partition> <mnt>, and copy
# /proc/vmcore to <mnt>/<path>/%DATE/.
# NOTE: <partition> can be a device node, label or uuid.
# It's recommended to use persistent device names
# such as /dev/vg/<devname>.
# Otherwise it's suggested to use label or uuid.
#
# path <path>
# - "path" represents the file system path in which vmcore
# will be saved. If a dump target is specified in
# kdump.conf, then "path" is relative to the specified
# dump target.
#
# Interpretation of "path" changes a bit if the user didn't
# specify any dump target explicitly in kdump.conf. In this
# case, "path" represents the absolute path from root. The
# dump target and adjusted path are arrived at automatically
# depending on what's mounted in the current system.
#
# Ignored for raw device dumps. If unset, will use the default
# "/var/crash".
#
# core_collector <command> <options>
# - This allows you to specify the command to copy
# the vmcore. The default is makedumpfile, which on
# some architectures can drastically reduce vmcore size.
# See /sbin/makedumpfile --help for a list of options.
# Note that the -i and -g options are not needed here,
# as the initrd will automatically be populated with a
# config file appropriate for the running kernel.
# The default core_collector for raw/ssh dump is:
# "makedumpfile -F -l --message-level 1 -d 31".
# The default core_collector for other targets is:
# "makedumpfile -l --message-level 1 -d 31".
#
# "makedumpfile -F" will create a flattened vmcore.
# You need to use "makedumpfile -R" to rearrange the dump data to
# a normal dumpfile readable with analysis tools. For example:
# "makedumpfile -R vmcore < vmcore.flat".
#
# For core_collector format details, you can refer to
# kexec-kdump-howto.txt or kdump.conf manpage.
#
# kdump_post <binary | script>
# - This directive allows you to run a executable binary
# or script after the vmcore dump process terminates.
# The exit status of the current dump process is fed to
# the executable binary or script as its first argument.
#
# kdump_pre <binary | script>
# - Works like the "kdump_post" directive, but instead of running
# after the dump process, runs immediately before it.
# Exit status of this binary is interpreted as follows:
# 0 - continue with dump process as usual
# non 0 - reboot the system
#
# extra_bins <binaries | shell scripts>
# - This directive allows you to specify additional binaries or
# shell scripts to be included in the kdump initrd.
# Generally they are useful in conjunction with a kdump_post
# or kdump_pre binary or script which depends on these extra_bins.
#
# extra_modules <module(s)>
# - This directive allows you to specify extra kernel modules
# that you want to be loaded in the kdump initrd.
# Multiple modules can be listed, separated by spaces, and any
# dependent modules will automatically be included.
#
# default <reboot | halt | poweroff | shell | dump_to_rootfs>
# - Action to perform in case dumping fails.
# reboot: Reboot the system.
# halt: Halt the system.
# poweroff: Power down the system.
# shell: Drop to a bash shell.
# Exiting the shell reboots the system.
# dump_to_rootfs: Dump vmcore to rootfs from initramfs context and
# reboot. Useful when non-root dump target is specified.
# The default option is "reboot".
#
# force_rebuild <0 | 1>
# - By default, kdump initrd will only be rebuilt when necessary.
# Specify 1 to force rebuilding kdump initrd every time when kdump
# service starts.
#
# force_no_rebuild <0 | 1>
# - By default, kdump initrd will be rebuilt when necessary.
# Specify 1 to bypass rebuilding of kdump initrd.
#
# force_no_rebuild and force_rebuild options are mutually
# exclusive and they should not be set to 1 simultaneously.
#
# override_resettable <0 | 1>
# - Usually an unresettable block device can't be a dump target.
# Specifying 1 when you want to dump even though the block
# target is unresettable
# By default, it is 0, which will not try dumping destined to fail.
#
# dracut_args <arg(s)>
# - Pass extra dracut options when rebuilding kdump initrd.
#
# fence_kdump_args <arg(s)>
# - Command line arguments for fence_kdump_send (it can contain
# all valid arguments except hosts to send notification to).
#
# fence_kdump_nodes <node(s)>
# - List of cluster node(s) except localhost, separated by spaces,
# to send fence_kdump notifications to.
# (this option is mandatory to enable fence_kdump).
#

#raw /dev/vg/lv_kdump
#ext4 /dev/vg/lv_kdump
#ext4 LABEL=/boot
#ext4 UUID=03138356-5e61-4ab3-b58e-27507ac41937
#nfs my.server.com:/export/tmp
#ssh user@my.server.com
#sshkey /root/.ssh/kdump_id_rsa
path /var/crash
core_collector makedumpfile -l --message-level 1 -d 31
#core_collector scp
#kdump_post /var/crash/scripts/kdump-post.sh
#kdump_pre /var/crash/scripts/kdump-pre.sh
#extra_bins /usr/bin/lftp
#extra_modules gfs2
#default shell
#force_rebuild 1
#force_no_rebuild 1
#dracut_args --omit-drivers "cfg80211 snd" --add-drivers "ext2 ext3"
#fence_kdump_args -p 7410 -f auto -c 0 -i 10
#fence_kdump_nodes node1 node2

344
SOURCES/kdump.conf.5

@ -0,0 +1,344 @@ @@ -0,0 +1,344 @@
.TH KDUMP.CONF 5 "07/23/2008" "kexec-tools"

.SH NAME
kdump.conf \- configuration file for kdump kernel.

.SH DESCRIPTION

kdump.conf is a configuration file for the kdump kernel crash
collection service.

kdump.conf provides post-kexec instructions to the kdump kernel. It is
stored in the initrd file managed by the kdump service. If you change
this file and do not want to reboot in order for the changes to take
effect, restart the kdump service to rebuild the initrd.

For most configurations, you can simply review the examples provided
in the stock /etc/kdump.conf.

.B NOTE:
For filesystem dumps the dump target must be mounted before building
kdump initramfs.

kdump.conf only affects the behavior of the initramfs. Please read the
kdump operational flow section of kexec-kdump-howto.txt in the docs to better
understand how this configuration file affects the behavior of kdump.

.SH OPTIONS

.B raw <partition>
.RS
Will dd /proc/vmcore into <partition>. Use persistent device names for
partition devices, such as /dev/vg/<devname>.
.RE

.B nfs <nfs mount>
.RS
Will mount nfs to <mnt>, and copy /proc/vmcore to <mnt>/<path>/%HOST-%DATE/,
supports DNS. Note that a fqdn should be used as the server name in the
mount point.
.RE

.B ssh <user@server>
.RS
Will scp /proc/vmcore to <user@server>:<path>/%HOST-%DATE/,
supports DNS. NOTE: make sure user has necessary write permissions on
server and that a fqdn is used as the server name.
.RE

.B sshkey <path>
.RS
Specify the path of the ssh key to use when dumping via ssh.
The default value is /root/.ssh/kdump_id_rsa.
.RE

.B <fs type> <partition>
.RS
Will mount -t <fs type> <partition> <mnt>, and copy /proc/vmcore to
<mnt>/<path>/%DATE/. NOTE: <partition> can be a device node, label
or uuid. It's recommended to use persistent device names such as
/dev/vg/<devname>. Otherwise it's suggested to use label or uuid.
.RE

.B path <path>
.RS
"path" represents the file system path in which vmcore will be saved.
If a dump target is specified in kdump.conf, then "path" is relative to the
specified dump target.
.PP
Interpretation of "path" changes a bit if the user didn't specify any dump
target explicitly in kdump.conf. In this case, "path" represents the
absolute path from root. The dump target and adjusted path are arrived
at automatically depending on what's mounted in the current system.
.PP
Ignored for raw device dumps. If unset, will use the default "/var/crash".
.RE

.B core_collector <command> <options>
.RS
This allows you to specify the command to copy the vmcore.
The default is makedumpfile, which on some architectures can drastically reduce
core file size. See /sbin/makedumpfile --help for a list of options.
Note that the -i and -g options are not needed here, as the initrd
will automatically be populated with a config file appropriate
for the running kernel.
.PP
Note 1: About default core collector:
The default core_collector for raw/ssh dump is:
"makedumpfile -F -l --message-level 1 -d 31".
The default core_collector for other targets is:
"makedumpfile -l --message-level 1 -d 31".
Even if core_collector option is commented out in kdump.conf, makedumpfile
is the default core collector and kdump uses it internally.
If one does not want makedumpfile as default core_collector, then they
need to specify one using core_collector option to change the behavior.
.PP
Note 2: If "makedumpfile -F" is used then you will get a flattened format
vmcore.flat, you will need to use "makedumpfile -R" to rearrange the
dump data from standard input to a normal dumpfile (readable with analysis
tools).
ie. "makedumpfile -R vmcore < vmcore.flat"

.RE

.B kdump_post <binary | script>
.RS
This directive allows you to run a specified executable
just after the vmcore dump process terminates. The exit
status of the current dump process is fed to the kdump_post
executable as its first argument($1). Executable can modify
it to indicate the new exit status of succeeding dump process,
.PP
Note that scripts written for use with this directive must use
the /bin/bash interpreter.
.RE

.B kdump_pre <binary | script>
.RS
Works just like the "kdump_post" directive, but instead
of running after the dump process, runs immediately
before. Exit status of this binary is interpreted
as follows:
.PP
0 - continue with dump process as usual
.PP
non 0 - reboot the system
.PP
Note that scripts written for this directive must use
the /bin/bash interpreter.
.RE

.B extra_bins <binaries | shell scripts>
.RS
This directive allows you to specify additional
binaries or shell scripts you'd like to include in
your kdump initrd. Generally only useful in
conjunction with a kdump_post binary or script that
relies on other binaries or scripts.
.RE

.B extra_modules <module(s)>
.RS
This directive allows you to specify extra kernel
modules that you want to be loaded in the kdump
initrd, typically used to set up access to
non-boot-path dump targets that might otherwise
not be accessible in the kdump environment. Multiple
modules can be listed, separated by spaces, and any
dependent modules will automatically be included.
.RE

.B default <reboot | halt | poweroff | shell | dump_to_rootfs>
.RS
Action to perform in case dumping to the intended target fails. The default is "reboot".
reboot: Reboot the system (this is what most people will want, as it returns the system
to a normal state). halt: Halt the system and lose the vmcore. poweroff: The system
will be powered down. shell: Drop to a shell session inside the initramfs, from which
you can manually perform additional recovery actions. Exiting this shell reboots the
system. Note: kdump uses bash as the default shell. dump_to_rootfs: If non-root dump
target is specified, the default action can be set as dump_to_rootfs. That means when
dumping to target fails, dump vmcore to rootfs from initramfs context and reboot.
.RE

.B force_rebuild <0 | 1>
.RS
By default, kdump initrd will only be rebuilt when necessary.
Specify 1 to force rebuilding kdump initrd every time when kdump service starts.
.RE

.B force_no_rebuild <0 | 1>
.RS
By default, kdump initrd will be rebuilt when necessary.
Specify 1 to bypass rebuilding of kdump initrd.

.PP
force_no_rebuild and force_rebuild options are mutually exclusive and
they should not be set to 1 simultaneously.
.RE

.B override_resettable <0 | 1>
.RS
Usually an unresettable block device can't be a dump target. Specifying 1 means
that even though the block target is unresettable, the user wants to try dumping anyway.
By default, it's set to 0, which will not try something destined to fail.
.RE


.B dracut_args <arg(s)>
.RS
Kdump uses dracut to generate initramfs for second kernel. This option
allows a user to pass arguments to dracut directly.
.RE


.B fence_kdump_args <arg(s)>
.RS
Command line arguments for fence_kdump_send (it can contain all valid
arguments except hosts to send notification to).
.RE


.B fence_kdump_nodes <node(s)>
.RS
List of cluster node(s) except localhost, separated by spaces, to send fence_kdump notification
to (this option is mandatory to enable fence_kdump).
.RE


.SH DEPRECATED OPTIONS

.B net <nfs mount>|<user@server>
.RS
net option is replaced by nfs and ssh options. Use nfs or ssh options
directly.
.RE

.B options <module> <option list>
.RS
Use KDUMP_COMMANDLINE_APPEND in /etc/sysconfig/kdump to add module options as
kernel command line parameters. For example, specify 'loop.max_loop=1' to limit
maximum loop devices to 1.
.RE

.B link_delay <seconds>
.RS
link_delay was used to wait for a network device to initialize before using it.
Now dracut network module takes care of this issue automatically.
.RE

.B disk_timeout <seconds>
.RS
Similar to link_delay, dracut ensures disks are ready before kdump uses them.
.RE

.B debug_mem_level <0-3>
.RS
Turn on verbose debug output of kdump scripts regarding free/used memory at
various points of execution. This feature has been
moved to dracut now.
Use KDUMP_COMMANDLINE_APPEND in /etc/sysconfig/kdump and
append dracut cmdline param rd.memdebug=[0-3] to enable the debug output.

Higher level means more debugging output.
.PP
0 - no output
.PP
1 - partial /proc/meminfo
.PP
2 - /proc/meminfo
.PP
3 - /proc/meminfo + /proc/slabinfo
.RE

.B blacklist <list of kernel modules>
.RS
blacklist option was recently being used to prevent loading modules in
initramfs. General terminology for blacklist has been that module is
present in initramfs but it is not actually loaded in kernel. Hence
retaining blacklist option creates more confusing behavior. It has been
deprecated.
.PP
Instead, use rd.driver.blacklist option on second kernel to blacklist
a certain module. One can edit /etc/sysconfig/kdump.conf and edit
KDUMP_COMMANDLINE_APPEND to pass kernel command line options. Refer
to dracut.cmdline man page for more details on module blacklist option.
.RE

.RE

.SH EXAMPLES
Here are some examples for core_collector option:
.PP
Core collector command format depends on dump target type. Typically for
filesystem (local/remote), core_collector should accept two arguments.
First one is source file and second one is target file. For ex.
.TP
ex1.
core_collector "cp --sparse=always"

Above will effectively be translated to:

cp --sparse=always /proc/vmcore <dest-path>/vmcore
.TP
ex2.
core_collector "makedumpfile -l --message-level 1 -d 31"

Above will effectively be translated to:

makedumpfile -l --message-level 1 -d 31 /proc/vmcore <dest-path>/vmcore
.PP
For dump targets like raw and ssh, in general, core collector should expect
one argument (source file) and should output the processed core on standard
output (There is one exception of "scp", discussed later). This standard
output will be saved to destination using appropriate commands.

raw dumps examples:
.TP
ex3.
core_collector "cat"

Above will effectively be translated to.

cat /proc/vmcore | dd of=<target-device>
.TP
ex4.
core_collector "makedumpfile -F -l --message-level 1 -d 31"

Above will effectively be translated to.

makedumpfile -F -l --message-level 1 -d 31 | dd of=<target-device>
.PP
ssh dumps examples
.TP
ex5.
core_collector "cat"

Above will effectively be translated to.

cat /proc/vmcore | ssh <options> <remote-location> "dd of=path/vmcore"
.TP
ex6.
core_collector "makedumpfile -F -l --message-level 1 -d 31"

Above will effectively be translated to.

makedumpfile -F -l --message-level 1 -d 31 | ssh <options> <remote-location> "dd of=path/vmcore"

There is one exception to standard output rule for ssh dumps. And that is
scp. As scp can handle ssh destinations for file transfers, one can
specify "scp" as core collector for ssh targets (no output on stdout).
.TP
ex7.
core_collector "scp"

Above will effectively be translated to.

scp /proc/vmcore <user@host>:path/vmcore

.PP
examples for other options please see
.I /etc/kdump.conf

.SH SEE ALSO

kexec(8) mkdumprd(8) dracut.cmdline(7)

14
SOURCES/kdump.service

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
[Unit]
Description=Crash recovery kernel arming
After=network.target network-online.target remote-fs.target basic.target
DefaultDependencies=no

[Service]
Type=oneshot
ExecStart=/usr/bin/kdumpctl start
ExecStop=/usr/bin/kdumpctl stop
RemainAfterExit=yes
StartLimitInterval=0

[Install]
WantedBy=multi-user.target

31
SOURCES/kdump.sysconfig

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug"

# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 reset_devices"

# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""

33
SOURCES/kdump.sysconfig.aarch64

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug"

# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="irqpoll nr_cpus=1 swiotlb=noforce cma=0 reset_devices cgroup_disable=memory udev.children-max=2 panic=10 rootflags=nofail"

# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"

KDUMP_BOOTDIR="/boot"
KDUMP_IMG="vmlinuz"

40
SOURCES/kdump.sysconfig.i386

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug"

# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="irqpoll nr_cpus=1 reset_devices numa=off udev.children-max=2 panic=10 rootflags=nofail transparent_hugepage=never"

# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""

#Where to find the boot image
#KDUMP_BOOTDIR="/boot"

#What is the image type used for kdump
KDUMP_IMG="vmlinuz"

#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""

32
SOURCES/kdump.sysconfig.ia64

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us append arguments to the current kdump commandline
# As taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 reset_devices"

# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""

#Where to find the boot image
KDUMP_BOOTDIR="/boot/efi/efi/redhat"

#What is the image type used for kdump
KDUMP_IMG="vmlinuz"

#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""

42
SOURCES/kdump.sysconfig.ppc64

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug"

# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 noirqdistrib reset_devices cgroup_disable=memory numa=off udev.children-max=2 ehea.use_mcs=0 panic=10 rootflags=nofail kvm_cma_resv_ratio=0 transparent_hugepage=never"

# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS="--dt-no-old-root"

#Where to find the boot image
#KDUMP_BOOTDIR="/boot"

#What is the image type used for kdump
KDUMP_IMG="vmlinuz"

#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""

#Specify the action after failure

42
SOURCES/kdump.sysconfig.ppc64le

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug"

# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="irqpoll maxcpus=1 noirqdistrib reset_devices cgroup_disable=memory numa=off udev.children-max=2 ehea.use_mcs=0 panic=10 rootflags=nofail kvm_cma_resv_ratio=0 transparent_hugepage=never"

# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS="--dt-no-old-root"

#Where to find the boot image
#KDUMP_BOOTDIR="/boot"

#What is the image type used for kdump
KDUMP_IMG="vmlinuz"

#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""

#Specify the action after failure

43
SOURCES/kdump.sysconfig.s390x

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug"

# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="nr_cpus=1 cgroup_disable=memory numa=off udev.children-max=2 panic=10 rootflags=nofail transparent_hugepage=never"

# Any additional /sbin/mkdumprd arguments required.
MKDUMPRD_ARGS=""

# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""

#Where to find the boot image
#KDUMP_BOOTDIR="/boot"

#What is the image type used for kdump
KDUMP_IMG="vmlinuz"

#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""

40
SOURCES/kdump.sysconfig.x86_64

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
# Kernel Version string for the -kdump kernel, such as 2.6.13-1544.FC5kdump
# If no version is specified, then the init script will try to find a
# kdump kernel with the same version number as the running kernel.
KDUMP_KERNELVER=""

# The kdump commandline is the command line that needs to be passed off to
# the kdump kernel. This will likely match the contents of the grub kernel
# line. For example:
# KDUMP_COMMANDLINE="ro root=LABEL=/"
# Dracut depends on proper root= options, so please make sure that appropriate
# root= options are copied from /proc/cmdline. In general it is best to append
# command line options using "KDUMP_COMMANDLINE_APPEND=".
# If a command line is not specified, the default will be taken from
# /proc/cmdline
KDUMP_COMMANDLINE=""

# This variable lets us remove arguments from the current kdump commandline
# as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline
# NOTE: some arguments such as crashkernel will always be removed
KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug kaslr"

# This variable lets us append arguments to the current kdump commandline
# after processed by KDUMP_COMMANDLINE_REMOVE
KDUMP_COMMANDLINE_APPEND="irqpoll nr_cpus=1 reset_devices cgroup_disable=memory mce=off numa=off udev.children-max=2 panic=10 rootflags=nofail acpi_no_memhotplug transparent_hugepage=never nokaslr"

# Any additional kexec arguments required. In most situations, this should
# be left empty
#
# Example:
# KEXEC_ARGS="--elf32-core-headers"
KEXEC_ARGS=""

#Where to find the boot image
#KDUMP_BOOTDIR="/boot"

#What is the image type used for kdump
KDUMP_IMG="vmlinuz"

#What is the images extension. Relocatable kernels don't have one
KDUMP_IMG_EXT=""

1323
SOURCES/kdumpctl

File diff suppressed because it is too large Load Diff

44
SOURCES/kdumpctl.8

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
.TH KDUMPCTL 8 2015-07-13 kexec-tools

.SH NAME
kdumpctl \- control interface for kdump

.SH SYNOPSIS
.B kdumpctl
.I COMMAND

.SH DESCRIPTION
.B kdumpctl
is used to check or control the kdump service.
In most cases, you should use
.B systemctl
to start / stop / enable kdump service instead. However,
.B kdumpctl
provides more details for debug and a helper to setup ssh key authentication.

.SH COMMANDS
.TP
.I start
Start the service.
.TP
.I stop
Stop the service.
.TP
.I status
Prints the current status of kdump service.
It returns non-zero value if kdump is not operational.
.TP
.I restart
Is equal to
.I start; stop
.TP
.I propagate
Helps to setup key authentication for ssh storage since it's
impossible to use password authentication during kdump.
.TP
.I showmem
Prints the size of reserved memory for crash kernel in megabytes.

.SH "SEE ALSO"
.BR kdump.conf (5),
.BR mkdumprd (8)

730
SOURCES/kexec-kdump-howto.txt

@ -0,0 +1,730 @@ @@ -0,0 +1,730 @@
Kexec/Kdump HOWTO

Introduction

Kexec and kdump are new features in the 2.6 mainstream kernel. These features
are included in Red Hat Enterprise Linux 5. The purpose of these features
is to ensure faster boot up and creation of reliable kernel vmcores for
diagnostic purposes.

Overview

Kexec

Kexec is a fastboot mechanism which allows booting a Linux kernel from the
context of already running kernel without going through BIOS. BIOS can be very
time consuming especially on the big servers with lots of peripherals. This can
save a lot of time for developers who end up booting a machine numerous times.

Kdump

Kdump is a new kernel crash dumping mechanism and is very reliable because
the crash dump is captured from the context of a freshly booted kernel and
not from the context of the crashed kernel. Kdump uses kexec to boot into
a second kernel whenever system crashes. This second kernel, often called
a capture kernel, boots with very little memory and captures the dump image.

The first kernel reserves a section of memory that the second kernel uses
to boot. Kexec enables booting the capture kernel without going through BIOS
hence contents of first kernel's memory are preserved, which is essentially
the kernel crash dump.

Kdump is supported on the i686, x86_64, ia64 and ppc64 platforms. The
standard kernel and capture kernel are one in the same on i686, x86_64,
ia64 and ppc64.

If you're reading this document, you should already have kexec-tools
installed. If not, you install it via the following command:

# yum install kexec-tools

Now load a kernel with kexec:

# kver=`uname -r` # kexec -l /boot/vmlinuz-$kver
--initrd=/boot/initrd-$kver.img \
--command-line="`cat /proc/cmdline`"

NOTE: The above will boot you back into the kernel you're currently running,
if you want to load a different kernel, substitute it in place of `uname -r`.

Now reboot your system, taking note that it should bypass the BIOS:

# reboot


How to configure kdump:

Again, we assume if you're reading this document, you should already have
kexec-tools installed. If not, you install it via the following command:

# yum install kexec-tools

To be able to do much of anything interesting in the way of debug analysis,
you'll also need to install the kernel-debuginfo package, of the same arch
as your running kernel, and the crash utility:

# yum --enablerepo=\*debuginfo install kernel-debuginfo.$(uname -m) crash

Next up, we need to modify some boot parameters to reserve a chunk of memory for
the capture kernel. With the help of grubby, it's very easy to append
"crashkernel=128M" to the end of your kernel boot parameters. Note that the X
values are such that X = the amount of memory to reserve for the capture kernel.
And based on arch and system configuration, one might require more than 128M to
be reserved for kdump. One need to experiment and test kdump, if 128M is not
sufficient, try reserving more memory.

# grubby --args="crashkernel=128M" --update-kernel=/boot/vmlinuz-`uname -r`

Note that there is an alternative form in which to specify a crashkernel
memory reservation, in the event that more control is needed over the size and
placement of the reserved memory. The format is:

crashkernel=range1:size1[,range2:size2,...][@offset]

Where range<n> specifies a range of values that are matched against the amount
of physical RAM present in the system, and the corresponding size<n> value
specifies the amount of kexec memory to reserve. For example:

crashkernel=512M-2G:64M,2G-:128M

This line tells kexec to reserve 64M of ram if the system contains between
512M and 2G of physical memory. If the system contains 2G or more of physical
memory, 128M should be reserved.

You can also use the default crashkernel=auto to let kernel set the
crashkernel size.

crashkernel=auto indicates a best effort estimation for usual use cases,
however one still needs do a test to ensure that the kernel reserved
memory size is enough.

NOTE:
When a debug variant kernel is used as the capture kernel and the
primary kernel was booted with 'crashkernel=auto' set in the bootargs,
the capture kernel boot can fail.

A debug variant kernel usually is the same stable kernel with some
debug options enabled which uses much more memory in the kdump kernel.
Thus when you use 'crashkernel=auto', kdump kernel will likely run out
of memory.

So it is not advisable to use a debug variant kernel as the capture
kernel when primary kernel is booted with 'crashkernel=auto' set in
bootargs.

After making said changes, reboot your system, so that the X MB of memory is
left untouched by the normal system, reserved for the capture kernel. Take note
that the output of 'free -m' will show X MB less memory than without this
parameter, which is expected. You may be able to get by with less than 128M, but
testing with only 64M has proven unreliable of late. On ia64, as much as 512M
may be required.

Now that you've got that reserved memory region set up, you want to turn on
the kdump init script:

# chkconfig kdump on

Then, start up kdump as well:

# systemctl start kdump.service

This should load your kernel-kdump image via kexec, leaving the system ready
to capture a vmcore upon crashing. To test this out, you can force-crash
your system by echo'ing a c into /proc/sysrq-trigger:

# echo c > /proc/sysrq-trigger

You should see some panic output, followed by the system restarting into
the kdump kernel. When the boot process gets to the point where it starts
the kdump service, your vmcore should be copied out to disk (by default,
in /var/crash/<YYYY-MM-DD-HH:MM>/vmcore), then the system rebooted back into
your normal kernel.

Once back to your normal kernel, you can use the previously installed crash
kernel in conjunction with the previously installed kernel-debuginfo to
perform postmortem analysis:

# crash /usr/lib/debug/lib/modules/2.6.17-1.2621.el5/vmlinux
/var/crash/2006-08-23-15:34/vmcore

crash> bt

and so on...

Saving vmcore-dmesg.txt
----------------------
Kernel log bufferes are one of the most important information available
in vmcore. Now before saving vmcore, kernel log bufferes are extracted
from /proc/vmcore and saved into a file vmcore-dmesg.txt. After
vmcore-dmesg.txt, vmcore is saved. Destination disk and directory for
vmcore-dmesg.txt is same as vmcore. Note that kernel log buffers will
not be available if dump target is raw device.

Dump Triggering methods:

This section talks about the various ways, other than a Kernel Panic, in which
Kdump can be triggered. The following methods assume that Kdump is configured
on your system, with the scripts enabled as described in the section above.

1) AltSysRq C

Kdump can be triggered with the combination of the 'Alt','SysRq' and 'C'
keyboard keys. Please refer to the following link for more details:

http://kbase.redhat.com/faq/FAQ_43_5559.shtm

In addition, on PowerPC boxes, Kdump can also be triggered via Hardware
Management Console(HMC) using 'Ctrl', 'O' and 'C' keyboard keys.

2) NMI_WATCHDOG

In case a machine has a hard hang, it is quite possible that it does not
respond to keyboard interrupts. As a result 'Alt-SysRq' keys will not help
trigger a dump. In such scenarios Nmi Watchdog feature can prove to be useful.
The following link has more details on configuring Nmi watchdog option.

http://kbase.redhat.com/faq/FAQ_85_9129.shtm

Once this feature has been enabled in the kernel, any lockups will result in an
OOPs message to be generated, followed by Kdump being triggered.

3) Kernel OOPs

If we want to generate a dump everytime the Kernel OOPses, we can achieve this
by setting the 'Panic On OOPs' option as follows:

# echo 1 > /proc/sys/kernel/panic_on_oops

This is enabled by default on RHEL5.

4) NMI(Non maskable interrupt) button

In cases where the system is in a hung state, and is not accepting keyboard
interrupts, using NMI button for triggering Kdump can be very useful. NMI
button is present on most of the newer x86 and x86_64 machines. Please refer
to the User guides/manuals to locate the button, though in most occasions it
is not very well documented. In most cases it is hidden behind a small hole
on the front or back panel of the machine. You could use a toothpick or some
other non-conducting probe to press the button.

For example, on the IBM X series 366 machine, the NMI button is located behind
a small hole on the bottom center of the rear panel.

To enable this method of dump triggering using NMI button, you will need to set
the 'unknown_nmi_panic' option as follows:

# echo 1 > /proc/sys/kernel/unknown_nmi_panic

5) PowerPC specific methods:

On IBM PowerPC machines, issuing a soft reset invokes the XMON debugger(if
XMON is configured). To configure XMON one needs to compile the kernel with
the CONFIG_XMON and CONFIG_XMON_DEFAULT options, or by compiling with
CONFIG_XMON and booting the kernel with xmon=on option.

Following are the ways to remotely issue a soft reset on PowerPC boxes, which
would drop you to XMON. Pressing a 'X' (capital alphabet X) followed by an
'Enter' here will trigger the dump.

5.1) HMC

Hardware Management Console(HMC) available on Power4 and Power5 machines allow
partitions to be reset remotely. This is specially useful in hang situations
where the system is not accepting any keyboard inputs.

Once you have HMC configured, the following steps will enable you to trigger
Kdump via a soft reset:

On Power4
Using GUI

* In the right pane, right click on the partition you wish to dump.
* Select "Operating System->Reset".
* Select "Soft Reset".
* Select "Yes".

Using HMC Commandline

# reset_partition -m <machine> -p <partition> -t soft

On Power5
Using GUI

* In the right pane, right click on the partition you wish to dump.
* Select "Restart Partition".
* Select "Dump".
* Select "OK".

Using HMC Commandline

# chsysstate -m <managed system name> -n <lpar name> -o dumprestart -r lpar

5.2) Blade Management Console for Blade Center

To initiate a dump operation, go to Power/Restart option under "Blade Tasks" in
the Blade Management Console. Select the corresponding blade for which you want
to initate the dump and then click "Restart blade with NMI". This issues a
system reset and invokes xmon debugger.


Advanced Setups:

In addition to being able to capture a vmcore to your system's local file
system, kdump can be configured to capture a vmcore to a number of other
locations, including a raw disk partition, a dedicated file system, an NFS
mounted file system, or a remote system via ssh/scp. Additional options
exist for specifying the relative path under which the dump is captured,
what to do if the capture fails, and for compressing and filtering the dump
(so as to produce smaller, more manageable, vmcore files).

In theory, dumping to a location other than the local file system should be
safer than kdump's default setup, as its possible the default setup will try
dumping to a file system that has become corrupted. The raw disk partition and
dedicated file system options allow you to still dump to the local system,
but without having to remount your possibly corrupted file system(s),
thereby decreasing the chance a vmcore won't be captured. Dumping to an
NFS server or remote system via ssh/scp also has this advantage, as well
as allowing for the centralization of vmcore files, should you have several
systems from which you'd like to obtain vmcore files. Of course, note that
these configurations could present problems if your network is unreliable.

Advanced setups are configured via modifications to /etc/kdump.conf,
which out of the box, is fairly well documented itself. Any alterations to
/etc/kdump.conf should be followed by a restart of the kdump service, so
the changes can be incorporated in the kdump initrd. Restarting the kdump
service is as simple as '/sbin/systemctl restart kdump.service'.


Note that kdump.conf is used as a configuration mechanism for capturing dump
files from the initramfs (in the interests of safety), the root file system is
mounted, and the init process is started, only as a last resort if the
initramfs fails to capture the vmcore. As such, configuration made in
/etc/kdump.conf is only applicable to capture recorded in the initramfs. If
for any reason the init process is started on the root file system, only a
simple copying of the vmcore from /proc/vmcore to /var/crash/$DATE/vmcore will
be preformed.

For both local filesystem and nfs dump the dump target must be mounted before
building kdump initramfs. That means one needs to put an entry for the dump
file system in /etc/fstab so that after reboot when kdump service starts,
it can find the dump target and build initramfs instead of failing.
Usually the dump target should be used only for kdump. If you worry about
someone uses the filesystem for something else other than dumping vmcore
you can mount it as read-only. Mkdumprd will still remount it as read-write
for creating dump directory and will move it back to read-only afterwards.

Raw partition

Raw partition dumping requires that a disk partition in the system, at least
as large as the amount of memory in the system, be left unformatted. Assuming
/dev/vg/lv_kdump is left unformatted, kdump.conf can be configured with
'raw /dev/vg/lv_kdump', and the vmcore file will be copied via dd directly
onto partition /dev/vg/lv_kdump. Restart the kdump service via
'/sbin/systemctl restart kdump.service' to commit this change to your kdump
initrd. Dump target should be persistent device name, such as lvm or device
mapper canonical name.

Dedicated file system

Similar to raw partition dumping, you can format a partition with the file
system of your choice, Again, it should be at least as large as the amount
of memory in the system. Assuming it should be at least as large as the
amount of memory in the system. Assuming /dev/vg/lv_kdump has been
formatted ext4, specify 'ext4 /dev/vg/lv_kdump' in kdump.conf, and a
vmcore file will be copied onto the file system after it has been mounted.
Dumping to a dedicated partition has the advantage that you can dump multiple
vmcores to the file system, space permitting, without overwriting previous ones,
as would be the case in a raw partition setup. Restart the kdump service via
'/sbin/systemctl restart kdump.service' to commit this change to
your kdump initrd. Note that for local file systems ext4 and ext2 are
supported as dumpable targets. Kdump will not prevent you from specifying
other filesystems, and they will most likely work, but their operation
cannot be guaranteed. for instance specifying a vfat filesystem or msdos
filesystem will result in a successful load of the kdump service, but during
crash recovery, the dump will fail if the system has more than 2GB of memory
(since vfat and msdos filesystems do not support more than 2GB files).
Be careful of your filesystem selection when using this target.

It is recommended to use persistent device names or UUID/LABEL for file system
dumps. One example of persistent device is /dev/vg/<devname>.

NFS mount

Dumping over NFS requires an NFS server configured to export a file system
with full read/write access for the root user. All operations done within
the kdump initial ramdisk are done as root, and to write out a vmcore file,
we obviously must be able to write to the NFS mount. Configuring an NFS
server is outside the scope of this document, but either the no_root_squash
or anonuid options on the NFS server side are likely of interest to permit
the kdump initrd operations write to the NFS mount as root.

Assuming your're exporting /dump on the machine nfs-server.example.com,
once the mount is properly configured, specify it in kdump.conf, via
'nfs nfs-server.example.com:/dump'. The server portion can be specified either
by host name or IP address. Following a system crash, the kdump initrd will
mount the NFS mount and copy out the vmcore to your NFS server. Restart the
kdump service via '/sbin/systemctl restart kdump.service' to commit this change
to your kdump initrd.

Special mount via "dracut_args"

You can utilize "dracut_args" to pass "--mount" to kdump, see dracut manpage
about the format of "--mount" for details. If there is any "--mount" specified
via "dracut_args", kdump will build it as the mount target without doing any
validation (mounting or checking like mount options, fs size, save path, etc),
so you must test it to ensure all the correctness. You cannot use other targets
in /etc/kdump.conf if you use "--mount" in "dracut_args". You also cannot specify
mutliple "--mount" targets via "dracut_args".

One use case of "--mount" in "dracut_args" is you do not want to mount dump target
before kdump service startup, for example, to reduce the burden of the shared nfs
server. Such as the example below:
dracut_args --mount "192.168.1.1:/share /mnt/test nfs4 defaults"

NOTE:
- <mountpoint> must be specified as an absolute path.

Remote system via ssh/scp

Dumping over ssh/scp requires setting up passwordless ssh keys for every
machine you wish to have dump via this method. First up, configure kdump.conf
for ssh/scp dumping, adding a config line of 'ssh user@server', where 'user'
can be any user on the target system you choose, and 'server' is the host
name or IP address of the target system. Using a dedicated, restricted user
account on the target system is recommended, as there will be keyless ssh
access to this account.

Once kdump.conf is appropriately configured, issue the command
'kdumpctl propagate' to automatically set up the ssh host keys and transmit
the necessary bits to the target server. You'll have to type in 'yes'
to accept the host key for your targer server if this is the first time
you've connected to it, and then input the target system user's password
to send over the necessary ssh key file. Restart the kdump service via
'/sbin/systemctl restart kdump.service' to commit this change to your kdump initrd.

Path
====
"path" represents the file system path in which vmcore will be saved. In
fact kdump creates a directory $hostip-$date with-in "path" and saves
vmcore there. So practically dump is saved in $path/$hostip-$date/. To
simplify discussion further, if we say dump will be saved in $path, it
is implied that kdump will create another directory inside path and
save vmcore there.

If a dump target is specified in kdump.conf, then "path" is relative to the
specified dump target. For example, if dump target is "ext4 /dev/sda", then
dump will be saved in "$path" directory on /dev/sda.

Same is the case for nfs dump. If user specified "nfs foo.com:/export/tmp/"
as dump target, then dump will effectively be saved in
"foo.com:/export/tmp/var/crash/" directory.

Interpretation of path changes a bit if user has not specified a dump
target explicitly in kdump.conf. In this case, "path" represents the
absolute path from root. And dump target and adjusted path are arrived
at automatically depending on what's mounted in the current system.

Following are few examples.

path /var/crash/
----------------
Assuming there is no disk mounted on /var/ or on /var/crash, dump will
be saved on disk backing rootfs in directory /var/crash.

path /var/crash/ (A separate disk mounted on /var)
--------------------------------------------------
Say a disk /dev/sdb is mouted on /var. In this case dump target will
become /dev/sdb and path will become "/crash" and dump will be saved
on "sdb:/crash/" directory.

path /var/crash/ (NFS mounted on /var)
-------------------------------------
Say foo.com:/export/tmp is mounted on /var. In this case dump target is
nfs server and path will be adjusted to "/crash" and dump will be saved to
foo.com:/export/tmp/crash/ directory.

Kdump boot directory
====================
Usually kdump kernel is the same as 1st kernel. So kdump will try to find
kdump kernel under /boot according to /proc/cmdline. E.g we execute below
command and get an output:
cat /proc/cmdline
BOOT_IMAGE=/xxx/vmlinuz-3.yyy.zzz root=xxxx .....
Then kdump kernel will be /boot/xxx/vmlinuz-3.yyy.zzz.
However a variable KDUMP_BOOTDIR in /etc/sysconfig/kdump is provided to
user if kdump kernel is put in a different directory.

Kdump Post-Capture Executable

It is possible to specify a custom script or binary you wish to run following
an attempt to capture a vmcore. The executable is passed an exit code from
the capture process, which can be used to trigger different actions from
within your post-capture executable.

Kdump Pre-Capture Executable

It is possible to specify a custom script or binary you wish to run before
capturing a vmcore. Exit status of this binary is interpreted:
0 - continue with dump process as usual
non 0 - reboot the system

Extra Binaries

If you have specific binaries or scripts you want to have made available
within your kdump initrd, you can specify them by their full path, and they
will be included in your kdump initrd, along with all dependent libraries.
This may be particularly useful for those running post-capture scripts that
rely on other binaries.

Extra Modules

By default, only the bare minimum of kernel modules will be included in your
kdump initrd. Should you wish to capture your vmcore files to a non-boot-path
storage device, such as an iscsi target disk or clustered file system, you may
need to manually specify additional kernel modules to load into your kdump
initrd.

Default action
==============
Default action specifies what to do when dump to configured dump target
fails. By default, default action is "reboot" and that is system reboots
if attempt to save dump to dump target fails.

There are other default actions available though.

- dump_to_rootfs
This option tries to mount root and save dump on root filesystem
in a path specified by "path". This option will generally make
sense when dump target is not root filesystem. For example, if
dump is being saved over network using "ssh" then one can specify
default to "dump_to_rootfs" to try saving dump to root filesystem
if dump over network fails.

- shell
Drop into a shell session inside initramfs.
- halt
Halt system after failure
- poweroff
Poweroff system after failure.

Compression and filtering

The 'core_collector' parameter in kdump.conf allows you to specify a custom
dump capture method. The most common alternate method is makedumpfile, which
is a dump filtering and compression utility provided with kexec-tools. On
some architectures, it can drastically reduce the size of your vmcore files,
which becomes very useful on systems with large amounts of memory.

A typical setup is 'core_collector makedumpfile -F -l --message-level 1 -d 31',
but check the output of '/sbin/makedumpfile --help' for a list of all available
options (-i and -g don't need to be specified, they're automatically taken care
of). Note that use of makedumpfile requires that the kernel-debuginfo package
corresponding with your running kernel be installed.

Core collector command format depends on dump target type. Typically for
filesystem (local/remote), core_collector should accept two arguments.
First one is source file and second one is target file. For ex.

ex1.
---
core_collector "cp --sparse=always"

Above will effectively be translated to:

cp --sparse=always /proc/vmcore <dest-path>/vmcore

ex2.
---
core_collector "makedumpfile -l --message-level 1 -d 31"

Above will effectively be translated to:

makedumpfile -l --message-level 1 -d 31 /proc/vmcore <dest-path>/vmcore


For dump targets like raw and ssh, in general, core collector should expect
one argument (source file) and should output the processed core on standard
output (There is one exception of "scp", discussed later). This standard
output will be saved to destination using appropriate commands.

raw dumps core_collector examples:
---------
ex3.
---
core_collector "cat"

Above will effectively be translated to.

cat /proc/vmcore | dd of=<target-device>

ex4.
---
core_collector "makedumpfile -F -l --message-level 1 -d 31"

Above will effectively be translated to.

makedumpfile -F -l --message-level 1 -d 31 | dd of=<target-device>

ssh dumps core_collector examples:
---------
ex5.
---
core_collector "cat"

Above will effectively be translated to.

cat /proc/vmcore | ssh <options> <remote-location> "dd of=path/vmcore"

ex6.
---
core_collector "makedumpfile -F -l --message-level 1 -d 31"

Above will effectively be translated to.

makedumpfile -F -l --message-level 1 -d 31 | ssh <options> <remote-location> "dd of=path/vmcore"

There is one exception to standard output rule for ssh dumps. And that is
scp. As scp can handle ssh destinations for file transfers, one can
specify "scp" as core collector for ssh targets (no output on stdout).

ex7.
----
core_collector "scp"

Above will effectively be translated to.

scp /proc/vmcore <user@host>:path/vmcore

About default core collector
----------------------------
Default core_collector for ssh/raw dump is:
"makedumpfile -F -l --message-level 1 -d 31".
Default core_collector for other targets is:
"makedumpfile -l --message-level 1 -d 31".

Even if core_collector option is commented out in kdump.conf, makedumpfile
is default core collector and kdump uses it internally.

If one does not want makedumpfile as default core_collector, then they
need to specify one using core_collector option to change the behavior.

Note: If "makedumpfile -F" is used then you will get a flattened format
vmcore.flat, you will need to use "makedumpfile -R" to rearrange the
dump data from stdard input to a normal dumpfile (readable with analysis
tools).
For example: "makedumpfile -R vmcore < vmcore.flat"

Caveats:

Console frame-buffers and X are not properly supported. If you typically run
with something along the lines of "vga=791" in your kernel config line or
have X running, console video will be garbled when a kernel is booted via
kexec. Note that the kdump kernel should still be able to create a dump,
and when the system reboots, video should be restored to normal.


Notes on resetting video:

Video is a notoriously difficult issue with kexec. Video cards contain ROM code
that controls their initial configuration and setup. This code is nominally
accessed and executed from the Bios, and otherwise not safely executable. Since
the purpose of kexec is to reboot the system without re-executing the Bios, it
is rather difficult if not impossible to reset video cards with kexec. The
result is, that if a system crashes while running in a graphical mode (i.e.
running X), the screen may appear to become 'frozen' while the dump capture is
taking place. A serial console will of course reveal that the system is
operating and capturing a vmcore image, but a casual observer will see the
system as hung until the dump completes and a true reboot is executed.

There are two possiblilties to work around this issue. One is by adding
--reset-vga to the kexec command line options in /etc/sysconfig/kdump. This
tells kdump to write some reasonable default values to the video card register
file, in the hopes of returning it to a text mode such that boot messages are
visible on the screen. It does not work with all video cards however.
Secondly, it may be worth trying to add vga15fb.ko to the extra_modules list in
/etc/kdump.conf. This will attempt to use the video card in framebuffer mode,
which can blank the screen prior to the start of a dump capture.

Notes on rootfs mount:
Dracut is designed to mount rootfs by default. If rootfs mounting fails it
will refuse to go on. So kdump leaves rootfs mounting to dracut currently.
We make the assumtion that proper root= cmdline is being passed to dracut
initramfs for the time being. If you need modify "KDUMP_COMMANDLINE=" in
/etc/sysconfig/kdump, you will need to make sure that appropriate root=
options are copied from /proc/cmdline. In general it is best to append
command line options using "KDUMP_COMMANDLINE_APPEND=" instead of replacing
the original command line completely.

Notes on watchdog module handling:

If a watchdog is active in first kernel then, we must have it's module
loaded in crash kernel, so that either watchdog is deactivated or started
being kicked in second kernel. Otherwise, we might face watchdog reboot
when vmcore is being saved. When dracut watchdog module is enabled, it
installs kernel watchdog module of active watchdog device in initrd.
kexec-tools always add "-a watchdog" to the dracut_args if there exists at
least one active watchdog and user has not added specifically "-o watchdog"
in dracut_args of kdump.conf. If a watchdog module (such as hp_wdt) has
not been written in watchdog-core framework then this option will not have
any effect and module will not be added. Please note that only systemd
watchdog daemon is supported as watchdog kick application.

Parallel Dumping Operation
==========================
Kexec allows kdump using multiple cpus. So parallel feature can accelerate
dumping substantially, especially in executing compression and filter.
For example:

1."makedumpfile -c --num-threads [THREAD_NUM] /proc/vmcore dumpfile"
2."makedumpfile -c /proc/vmcore dumpfile",

1 has better performance than 2, if THREAD_NUM is larger than two
and the usable cpus number is larger than THREAD_NUM.

Notes on how to use multiple cpus on a capture kernel on x86 system:

Make sure that you are using a kernel that supports disable_cpu_apicid
kernel option as a capture kernel, which is needed to avoid x86 specific
hardware issue (*). The disable_cpu_apicid kernel option is automatically
appended by kdumpctl script and is ignored if the kernel doesn't support it.

You need to specify how many cpus to be used in a capture kernel by specifying
the number of cpus in nr_cpus kernel option in /etc/sysconfig/kdump. nr_cpus
is 1 at default.

You should use necessary and sufficient number of cpus on a capture kernel.
Warning: Don't use too many cpus on a capture kernel, or the capture kernel
may lead to panic due to Out Of Memory.

(*) Without disable_cpu_apicid kernel option, capture kernel may lead to
hang, system reset or power-off at boot, depending on your system and runtime
situation at the time of crash.

Debugging Tips
--------------
- One can drop into a shell before/after saving vmcore with the help of
using kdump_pre/kdump_post hooks. Use following in one of the pre/post
scripts to drop into a shell.

#!/bin/bash
_ctty=/dev/ttyS0
setsid /bin/sh -i -l 0<>$_ctty 1<>$_ctty 2<>$_ctty

One might have to change the terminal depending on what they are using.

- Serial console logging for virtual machines

I generally use "virsh console <domain-name>" to get to serial console.
I noticed after dump saving system reboots and when grub menu shows up
some of the previously logged messages are no more there. That means
any important debugging info at the end will be lost.

One can log serial console as follows to make sure messages are not lost.

virsh ttyconsole <domain-name>
ln -s <name-of-tty> /dev/modem
minicom -C /tmp/console-logs

Now minicom should be logging serial console in file console-logs.


40
SOURCES/kexec-tools-2.0.14-Only-print-debug-message-when-failed-to-serach-for-k.patch

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
From f85183096d31d865c97565614535d84943b12908 Mon Sep 17 00:00:00 2001
Message-Id: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
From: Baoquan He <bhe@redhat.com>
Date: Fri, 3 Mar 2017 11:52:15 +0800
Subject: [PATCH 01/10] Only print debug message when failed to serach for
kernel symbol from /proc/kallsyms

Kernel symbol page_offset_base could be unavailable when mm KASLR code is
not compiled in kernel. It's inappropriate to print out error message
when failed to search for page_offset_base from /proc/kallsyms. Seems now
there is not a way to find out if mm KASLR is compiled in or not. An
alternative approach is only printing out debug message in get_kernel_sym
if failed to search a expected kernel symbol.

Do it in this patch, a simple fix.

Signed-off-by: Baoquan He <bhe@redhat.com>
Reviewed-by: Pratyush Anand <panand@redhat.com>
Acked-by: Dave Young <dyoung@redhat.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
kexec/arch/i386/crashdump-x86.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 88aeee33572b..c4cf2013a001 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -127,7 +127,7 @@ static unsigned long long get_kernel_sym(const char *symbol)
}
}
- fprintf(stderr, "Cannot get kernel %s symbol address\n", symbol);
+ dbgprintf("Cannot get kernel %s symbol address\n", symbol);
return 0;
}
--
2.9.3

76
SOURCES/kexec-tools-2.0.14-arm64-identify-PHYS_OFFSET-correctly.patch

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
From 7a4381e2042e2be308c96bc927145bc39a0594cc Mon Sep 17 00:00:00 2001
Message-Id: <7a4381e2042e2be308c96bc927145bc39a0594cc.1489676829.git.panand@redhat.com>
In-Reply-To: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
References: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Date: Wed, 15 Mar 2017 18:38:18 +0900
Subject: [PATCH 04/10] arm64: identify PHYS_OFFSET correctly

Due to the kernel patch, commit e7cd190385d1 ("arm64: mark reserved
memblock regions explicitly in iomem"), the current code will not be able
to identify the correct value of PHYS_OFFSET if some "reserved" memory
region, which is likely to be UEFI runtime services code/data, exists at
an address below the first "System RAM" regions.

This patch fixes this issue.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
kexec/arch/arm64/iomem.h | 7 +++++++
kexec/arch/arm64/kexec-arm64.c | 12 ++++++++++--
2 files changed, 17 insertions(+), 2 deletions(-)
create mode 100644 kexec/arch/arm64/iomem.h

diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h
new file mode 100644
index 000000000000..7fd66eb063e1
--- /dev/null
+++ b/kexec/arch/arm64/iomem.h
@@ -0,0 +1,7 @@
+#ifndef IOMEM_H
+#define IOMEM_H
+
+#define SYSTEM_RAM "System RAM\n"
+#define IOMEM_RESERVED "reserved\n"
+
+#endif
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 04fd3968bb52..d02b9dac3d33 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -21,6 +21,7 @@
#include "crashdump-arm64.h"
#include "dt-ops.h"
#include "fs2dt.h"
+#include "iomem.h"
#include "kexec-syscall.h"
#include "arch/options.h"
@@ -476,7 +477,14 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
return -1;
r = (struct memory_range *)data + nr;
- r->type = RANGE_RAM;
+
+ if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)))
+ r->type = RANGE_RAM;
+ else if (!strncmp(str, IOMEM_RESERVED, strlen(IOMEM_RESERVED)))
+ r->type = RANGE_RESERVED;
+ else
+ return 1;
+
r->start = base;
r->end = base + length - 1;
@@ -495,7 +503,7 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
static int get_memory_ranges_iomem(struct memory_range *array,
unsigned int *count)
{
- *count = kexec_iomem_for_each_line("System RAM\n",
+ *count = kexec_iomem_for_each_line(NULL,
get_memory_ranges_iomem_cb, array);
if (!*count) {
--
2.9.3

52
SOURCES/kexec-tools-2.0.14-arm64-kdump-Add-support-for-binary-image-files.patch

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
From ba77ebdac0d49ac128f4d31a5fd86e8165ce916a Mon Sep 17 00:00:00 2001
Message-Id: <ba77ebdac0d49ac128f4d31a5fd86e8165ce916a.1489676829.git.panand@redhat.com>
In-Reply-To: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
References: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
From: Pratyush Anand <panand@redhat.com>
Date: Wed, 15 Mar 2017 18:38:24 +0900
Subject: [PATCH 10/10] arm64: kdump: Add support for binary image files

This patch adds support to use binary image ie arch/arm64/boot/Image with
kdump.

Signed-off-by: Pratyush Anand <panand@redhat.com>
[takahiro.akashi@linaro.org: a bit reworked]
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
kexec/arch/arm64/kexec-image-arm64.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
index 960ed9667a4d..982e431e6d22 100644
--- a/kexec/arch/arm64/kexec-image-arm64.c
+++ b/kexec/arch/arm64/kexec-image-arm64.c
@@ -4,7 +4,9 @@
#define _GNU_SOURCE
+#include "crashdump-arm64.h"
#include "kexec-arm64.h"
+#include "kexec-syscall.h"
#include <limits.h>
int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
@@ -58,6 +60,16 @@ int image_arm64_load(int argc, char **argv, const char *kernel_buf,
dbgprintf("%s: PE format: %s\n", __func__,
(arm64_header_check_pe_sig(header) ? "yes" : "no"));
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ /* create and initialize elf core header segment */
+ result = load_crashdump_segments(info);
+ if (result) {
+ dbgprintf("%s: Creating eflcorehdr failed.\n",
+ __func__);
+ goto exit;
+ }
+ }
+
/* load the kernel */
add_segment_phys_virt(info, kernel_buf, kernel_size,
kernel_segment + arm64_mem.text_offset,
--
2.9.3

282
SOURCES/kexec-tools-2.0.14-arm64-kdump-add-DT-properties-to-crash-dump-kernel-s.patch

@ -0,0 +1,282 @@ @@ -0,0 +1,282 @@
From 7c59b94be4abf8b28dd02bae8b79542377a86618 Mon Sep 17 00:00:00 2001
Message-Id: <7c59b94be4abf8b28dd02bae8b79542377a86618.1489676829.git.panand@redhat.com>
In-Reply-To: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
References: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Date: Wed, 15 Mar 2017 18:38:23 +0900
Subject: [PATCH 09/10] arm64: kdump: add DT properties to crash dump kernel's
dtb

We pass the following properties to crash dump kernel:
linux,elfcorehdr: elf core header segment,
same as "elfcorehdr=" kernel parameter on other archs
linux,usable-memory-range: usable memory reserved for crash dump kernel

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
kexec/arch/arm64/kexec-arm64.c | 197 ++++++++++++++++++++++++++++++++++++-
kexec/arch/arm64/kexec-elf-arm64.c | 5 -
2 files changed, 192 insertions(+), 10 deletions(-)

diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 5e30107b043f..f3f101d1be48 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -25,6 +25,14 @@
#include "kexec-syscall.h"
#include "arch/options.h"
+#define ROOT_NODE_ADDR_CELLS_DEFAULT 1
+#define ROOT_NODE_SIZE_CELLS_DEFAULT 1
+
+#define PROP_ADDR_CELLS "#address-cells"
+#define PROP_SIZE_CELLS "#size-cells"
+#define PROP_ELFCOREHDR "linux,elfcorehdr"
+#define PROP_USABLE_MEM_RANGE "linux,usable-memory-range"
+
/* Global varables the core kexec routines expect. */
unsigned char reuse_initrd;
@@ -128,9 +136,6 @@ int arch_process_options(int argc, char **argv)
case OPT_INITRD:
arm64_opts.initrd = optarg;
break;
- case OPT_PANIC:
- die("load-panic (-p) not supported");
- break;
default:
break; /* Ignore core and unknown options. */
}
@@ -281,12 +286,115 @@ on_success:
return 0;
}
+static int get_cells_size(void *fdt, uint32_t *address_cells,
+ uint32_t *size_cells)
+{
+ int nodeoffset;
+ const uint32_t *prop = NULL;
+ int prop_len;
+
+ /* default values */
+ *address_cells = ROOT_NODE_ADDR_CELLS_DEFAULT;
+ *size_cells = ROOT_NODE_SIZE_CELLS_DEFAULT;
+
+ /* under root node */
+ nodeoffset = fdt_path_offset(fdt, "/");
+ if (nodeoffset < 0)
+ goto on_error;
+
+ prop = fdt_getprop(fdt, nodeoffset, PROP_ADDR_CELLS, &prop_len);
+ if (prop) {
+ if (prop_len == sizeof(*prop))
+ *address_cells = fdt32_to_cpu(*prop);
+ else
+ goto on_error;
+ }
+
+ prop = fdt_getprop(fdt, nodeoffset, PROP_SIZE_CELLS, &prop_len);
+ if (prop) {
+ if (prop_len == sizeof(*prop))
+ *size_cells = fdt32_to_cpu(*prop);
+ else
+ goto on_error;
+ }
+
+ dbgprintf("%s: #address-cells:%d #size-cells:%d\n", __func__,
+ *address_cells, *size_cells);
+ return 0;
+
+on_error:
+ return -EFAILED;
+}
+
+bool cells_size_fitted(uint32_t address_cells, uint32_t size_cells,
+ struct memory_range *range)
+{
+ dbgprintf("%s: %llx-%llx\n", __func__, range->start, range->end);
+
+ /* if *_cells >= 2, cells can hold 64-bit values anyway */
+ if ((address_cells == 1) && (range->start >= (1ULL << 32)))
+ return false;
+
+ if ((size_cells == 1) &&
+ ((range->end - range->start + 1) >= (1ULL << 32)))
+ return false;
+
+ return true;
+}
+
+static void fill_property(void *buf, uint64_t val, uint32_t cells)
+{
+ uint32_t val32;
+ int i;
+
+ if (cells == 1) {
+ val32 = cpu_to_fdt32((uint32_t)val);
+ memcpy(buf, &val32, sizeof(uint32_t));
+ } else {
+ for (i = 0;
+ i < (cells * sizeof(uint32_t) - sizeof(uint64_t)); i++)
+ *(char *)buf++ = 0;
+
+ val = cpu_to_fdt64(val);
+ memcpy(buf, &val, sizeof(uint64_t));
+ }
+}
+
+static int setprop_range(void *fdt, int nodeoffset,
+ const char *name, struct memory_range *range,
+ uint32_t address_cells, uint32_t size_cells)
+{
+ void *buf, *prop;
+ size_t buf_size;
+ int result;
+
+ buf_size = (address_cells + size_cells) * sizeof(uint32_t);
+ prop = buf = xmalloc(buf_size);
+
+ fill_property(prop, range->start, address_cells);
+ prop += address_cells * sizeof(uint32_t);
+
+ fill_property(prop, range->end - range->start + 1, size_cells);
+ prop += size_cells * sizeof(uint32_t);
+
+ result = fdt_setprop(fdt, nodeoffset, name, buf, buf_size);
+
+ free(buf);
+
+ return result;
+}
+
/**
* setup_2nd_dtb - Setup the 2nd stage kernel's dtb.
*/
-static int setup_2nd_dtb(struct dtb *dtb, char *command_line)
+static int setup_2nd_dtb(struct dtb *dtb, char *command_line, int on_crash)
{
+ uint32_t address_cells, size_cells;
+ int range_len;
+ int nodeoffset;
+ char *new_buf = NULL;
+ int new_size;
int result;
result = fdt_check_header(dtb->buf);
@@ -298,8 +406,86 @@ static int setup_2nd_dtb(struct dtb *dtb, char *command_line)
result = set_bootargs(dtb, command_line);
+ if (on_crash) {
+ /* determine #address-cells and #size-cells */
+ result = get_cells_size(dtb->buf, &address_cells, &size_cells);
+ if (result) {
+ fprintf(stderr,
+ "kexec: cannot determine cells-size.\n");
+ result = -EINVAL;
+ goto on_error;
+ }
+
+ if (!cells_size_fitted(address_cells, size_cells,
+ &elfcorehdr_mem)) {
+ fprintf(stderr,
+ "kexec: elfcorehdr doesn't fit cells-size.\n");
+ result = -EINVAL;
+ goto on_error;
+ }
+
+ if (!cells_size_fitted(address_cells, size_cells,
+ &crash_reserved_mem)) {
+ fprintf(stderr,
+ "kexec: usable memory range doesn't fit cells-size.\n");
+ result = -EINVAL;
+ goto on_error;
+ }
+
+ /* duplicate dt blob */
+ range_len = sizeof(uint32_t) * (address_cells + size_cells);
+ new_size = fdt_totalsize(dtb->buf)
+ + fdt_prop_len(PROP_ELFCOREHDR, range_len)
+ + fdt_prop_len(PROP_USABLE_MEM_RANGE, range_len);
+
+ new_buf = xmalloc(new_size);
+ result = fdt_open_into(dtb->buf, new_buf, new_size);
+ if (result) {
+ dbgprintf("%s: fdt_open_into failed: %s\n", __func__,
+ fdt_strerror(result));
+ result = -ENOSPC;
+ goto on_error;
+ }
+
+ /* add linux,elfcorehdr */
+ nodeoffset = fdt_path_offset(new_buf, "/chosen");
+ result = setprop_range(new_buf, nodeoffset,
+ PROP_ELFCOREHDR, &elfcorehdr_mem,
+ address_cells, size_cells);
+ if (result) {
+ dbgprintf("%s: fdt_setprop failed: %s\n", __func__,
+ fdt_strerror(result));
+ result = -EINVAL;
+ goto on_error;
+ }
+
+ /* add linux,usable-memory-range */
+ nodeoffset = fdt_path_offset(new_buf, "/chosen");
+ result = setprop_range(new_buf, nodeoffset,
+ PROP_USABLE_MEM_RANGE, &crash_reserved_mem,
+ address_cells, size_cells);
+ if (result) {
+ dbgprintf("%s: fdt_setprop failed: %s\n", __func__,
+ fdt_strerror(result));
+ result = -EINVAL;
+ goto on_error;
+ }
+
+ fdt_pack(new_buf);
+ dtb->buf = new_buf;
+ dtb->size = fdt_totalsize(new_buf);
+ }
+
dump_reservemap(dtb);
+
+ return result;
+
+on_error:
+ fprintf(stderr, "kexec: %s failed.\n", __func__);
+ if (new_buf)
+ free(new_buf);
+
return result;
}
@@ -367,7 +553,8 @@ int arm64_load_other_segments(struct kexec_info *info,
}
}
- result = setup_2nd_dtb(&dtb, command_line);
+ result = setup_2nd_dtb(&dtb, command_line,
+ info->kexec_flags & KEXEC_ON_CRASH);
if (result)
return -EFAILED;
diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
index 842ce21e2387..b17a31afa24e 100644
--- a/kexec/arch/arm64/kexec-elf-arm64.c
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
@@ -47,11 +47,6 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
int result;
int i;
- if (info->kexec_flags & KEXEC_ON_CRASH) {
- fprintf(stderr, "kexec: kdump not yet supported on arm64\n");
- return -EFAILED;
- }
-
result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0);
if (result < 0) {
--
2.9.3

191
SOURCES/kexec-tools-2.0.14-arm64-kdump-add-elf-core-header-segment.patch

@ -0,0 +1,191 @@ @@ -0,0 +1,191 @@
From dd3886b82ed56c18d9d6d0e7228a2b31eed0ec5a Mon Sep 17 00:00:00 2001
Message-Id: <dd3886b82ed56c18d9d6d0e7228a2b31eed0ec5a.1489676829.git.panand@redhat.com>
In-Reply-To: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
References: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Date: Wed, 15 Mar 2017 18:38:20 +0900
Subject: [PATCH 06/10] arm64: kdump: add elf core header segment

Elf core header contains the information necessary for the coredump of
the 1st kernel, including its physcal memory layout as well as cpu register
states at the panic.
The segment is allocated inside the reserved memory of crash dump kernel.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
kexec/arch/arm64/crashdump-arm64.c | 96 ++++++++++++++++++++++++++++++++++++++
kexec/arch/arm64/crashdump-arm64.h | 3 ++
kexec/arch/arm64/iomem.h | 2 +
kexec/arch/arm64/kexec-elf-arm64.c | 10 ++++
4 files changed, 111 insertions(+)

diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
index dcaca434af62..83461312d412 100644
--- a/kexec/arch/arm64/crashdump-arm64.c
+++ b/kexec/arch/arm64/crashdump-arm64.c
@@ -39,6 +39,39 @@ struct memory_ranges usablemem_rgns = {
.ranges = &crash_reserved_mem,
};
+struct memory_range elfcorehdr_mem;
+
+static struct crash_elf_info elf_info = {
+ .class = ELFCLASS64,
+#if (__BYTE_ORDER == __LITTLE_ENDIAN)
+ .data = ELFDATA2LSB,
+#else
+ .data = ELFDATA2MSB,
+#endif
+ .machine = EM_AARCH64,
+};
+
+/*
+ * Note: The returned value is correct only if !CONFIG_RANDOMIZE_BASE.
+ */
+static uint64_t get_kernel_page_offset(void)
+{
+ int i;
+
+ if (elf_info.kern_vaddr_start == UINT64_MAX)
+ return UINT64_MAX;
+
+ /* Current max virtual memory range is 48-bits. */
+ for (i = 48; i > 0; i--)
+ if (!(elf_info.kern_vaddr_start & (1UL << i)))
+ break;
+
+ if (i <= 0)
+ return UINT64_MAX;
+ else
+ return UINT64_MAX << i;
+}
+
/*
* iomem_range_callback() - callback called for each iomem region
* @data: not used
@@ -62,6 +95,10 @@ static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0)
return mem_regions_add(&crash_memory_rgns,
base, length, RANGE_RAM);
+ else if (strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) == 0)
+ elf_info.kern_paddr_start = base;
+ else if (strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) == 0)
+ elf_info.kern_size = base + length - elf_info.kern_paddr_start;
return 0;
}
@@ -115,5 +152,64 @@ static int crash_get_memory_ranges(void)
dbgprint_mem_range("Coredump memory ranges",
crash_memory_rgns.ranges, crash_memory_rgns.size);
+ /*
+ * For additional kernel code/data segment.
+ * kern_paddr_start/kern_size are determined in iomem_range_callback
+ */
+ elf_info.kern_vaddr_start = get_kernel_sym("_text");
+ if (!elf_info.kern_vaddr_start)
+ elf_info.kern_vaddr_start = UINT64_MAX;
+
+ return 0;
+}
+
+/*
+ * load_crashdump_segments() - load the elf core header
+ * @info: kexec info structure
+ *
+ * This function creates and loads an additional segment of elf core header
+ : which is used to construct /proc/vmcore on crash dump kernel.
+ *
+ * Return 0 in case of success and -1 in case of error.
+ */
+
+int load_crashdump_segments(struct kexec_info *info)
+{
+ unsigned long elfcorehdr;
+ unsigned long bufsz;
+ void *buf;
+ int err;
+
+ /*
+ * First fetch all the memory (RAM) ranges that we are going to
+ * pass to the crash dump kernel during panic.
+ */
+
+ err = crash_get_memory_ranges();
+
+ if (err)
+ return err;
+
+ elf_info.page_offset = get_kernel_page_offset();
+ dbgprintf("%s: page_offset: %016llx\n", __func__,
+ elf_info.page_offset);
+
+ err = crash_create_elf64_headers(info, &elf_info,
+ crash_memory_rgns.ranges, crash_memory_rgns.size,
+ &buf, &bufsz, ELF_CORE_HEADER_ALIGN);
+
+ if (err)
+ return err;
+
+ elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 0,
+ crash_reserved_mem.start, crash_reserved_mem.end,
+ -1, 0);
+
+ elfcorehdr_mem.start = elfcorehdr;
+ elfcorehdr_mem.end = elfcorehdr + bufsz - 1;
+
+ dbgprintf("%s: elfcorehdr 0x%llx-0x%llx\n", __func__,
+ elfcorehdr_mem.start, elfcorehdr_mem.end);
+
return 0;
}
diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
index 07a0ed0bc344..da75a2d0c5f1 100644
--- a/kexec/arch/arm64/crashdump-arm64.h
+++ b/kexec/arch/arm64/crashdump-arm64.h
@@ -18,5 +18,8 @@
extern struct memory_ranges usablemem_rgns;
extern struct memory_range crash_reserved_mem;
+extern struct memory_range elfcorehdr_mem;
+
+extern int load_crashdump_segments(struct kexec_info *info);
#endif /* CRASHDUMP_ARM64_H */
diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h
index 20cda87dbd02..d4864bb44922 100644
--- a/kexec/arch/arm64/iomem.h
+++ b/kexec/arch/arm64/iomem.h
@@ -2,6 +2,8 @@
#define IOMEM_H
#define SYSTEM_RAM "System RAM\n"
+#define KERNEL_CODE "Kernel code\n"
+#define KERNEL_DATA "Kernel data\n"
#define CRASH_KERNEL "Crash kernel\n"
#define IOMEM_RESERVED "reserved\n"
diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
index daf8bf0df9c4..c70a37ae7732 100644
--- a/kexec/arch/arm64/kexec-elf-arm64.c
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
@@ -119,6 +119,16 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
dbgprintf("%s: PE format: %s\n", __func__,
(arm64_header_check_pe_sig(header) ? "yes" : "no"));
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ /* create and initialize elf core header segment */
+ result = load_crashdump_segments(info);
+ if (result) {
+ dbgprintf("%s: Creating eflcorehdr failed.\n",
+ __func__);
+ goto exit;
+ }
+ }
+
/* load the kernel */
result = elf_exec_load(&ehdr, info);
--
2.9.3

202
SOURCES/kexec-tools-2.0.14-arm64-kdump-identify-memory-regions.patch

@ -0,0 +1,202 @@ @@ -0,0 +1,202 @@
From 2fa1ef9e45b3ce6f7977a2518e58e177934f377c Mon Sep 17 00:00:00 2001
Message-Id: <2fa1ef9e45b3ce6f7977a2518e58e177934f377c.1489676829.git.panand@redhat.com>
In-Reply-To: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
References: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Date: Wed, 15 Mar 2017 18:38:19 +0900
Subject: [PATCH 05/10] arm64: kdump: identify memory regions

The following regions need to be identified for later use:
a) memory regions which belong to the 1st kernel
b) usable memory reserved for crash dump kernel

We go through /proc/iomem to find out a) and b) which are marked
as "System RAM" and "Crash kernel", respectively.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
kexec/arch/arm64/Makefile | 2 +
kexec/arch/arm64/crashdump-arm64.c | 100 ++++++++++++++++++++++++++++++++++++-
kexec/arch/arm64/crashdump-arm64.h | 14 +++++-
kexec/arch/arm64/iomem.h | 1 +
4 files changed, 114 insertions(+), 3 deletions(-)

diff --git a/kexec/arch/arm64/Makefile b/kexec/arch/arm64/Makefile
index 74b677f7784e..2d4ae0eed9e0 100644
--- a/kexec/arch/arm64/Makefile
+++ b/kexec/arch/arm64/Makefile
@@ -6,6 +6,8 @@ arm64_FS2DT_INCLUDE += \
arm64_DT_OPS += kexec/dt-ops.c
+arm64_MEM_REGIONS = kexec/mem_regions.c
+
arm64_CPPFLAGS += -I $(srcdir)/kexec/
arm64_KEXEC_SRCS += \
diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
index d2272c8124d0..dcaca434af62 100644
--- a/kexec/arch/arm64/crashdump-arm64.c
+++ b/kexec/arch/arm64/crashdump-arm64.c
@@ -1,5 +1,13 @@
/*
* ARM64 crashdump.
+ * partly derived from arm implementation
+ *
+ * Copyright (c) 2014-2016 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*/
#define _GNU_SOURCE
@@ -10,12 +18,102 @@
#include "kexec.h"
#include "crashdump.h"
#include "crashdump-arm64.h"
+#include "iomem.h"
#include "kexec-arm64.h"
#include "kexec-elf.h"
+#include "mem_regions.h"
-struct memory_ranges usablemem_rgns = {};
+/* memory ranges on crashed kernel */
+static struct memory_range crash_memory_ranges[CRASH_MAX_MEMORY_RANGES];
+static struct memory_ranges crash_memory_rgns = {
+ .size = 0,
+ .max_size = CRASH_MAX_MEMORY_RANGES,
+ .ranges = crash_memory_ranges,
+};
+
+/* memory range reserved for crashkernel */
+struct memory_range crash_reserved_mem;
+struct memory_ranges usablemem_rgns = {
+ .size = 0,
+ .max_size = 1,
+ .ranges = &crash_reserved_mem,
+};
+
+/*
+ * iomem_range_callback() - callback called for each iomem region
+ * @data: not used
+ * @nr: not used
+ * @str: name of the memory region
+ * @base: start address of the memory region
+ * @length: size of the memory region
+ *
+ * This function is called once for each memory region found in /proc/iomem.
+ * It locates system RAM and crashkernel reserved memory and places these to
+ * variables, respectively, crash_memory_ranges and crash_reserved_mem.
+ */
+
+static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr),
+ char *str, unsigned long long base,
+ unsigned long long length)
+{
+ if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0)
+ return mem_regions_add(&usablemem_rgns,
+ base, length, RANGE_RAM);
+ else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0)
+ return mem_regions_add(&crash_memory_rgns,
+ base, length, RANGE_RAM);
+
+ return 0;
+}
int is_crashkernel_mem_reserved(void)
{
+ if (!crash_reserved_mem.end)
+ kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL);
+
+ return crash_reserved_mem.start != crash_reserved_mem.end;
+}
+
+/*
+ * crash_get_memory_ranges() - read system physical memory
+ *
+ * Function reads through system physical memory and stores found memory
+ * regions in crash_memory_ranges.
+ * Regions are sorted in ascending order.
+ *
+ * Returns 0 in case of success and -1 otherwise (errno is set).
+ */
+static int crash_get_memory_ranges(void)
+{
+ /*
+ * First read all memory regions that can be considered as
+ * system memory including the crash area.
+ */
+ if (!usablemem_rgns.size)
+ kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL);
+
+ /* allow only a single region for crash dump kernel */
+ if (usablemem_rgns.size != 1) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ dbgprint_mem_range("Reserved memory range", &crash_reserved_mem, 1);
+
+ if (mem_regions_exclude(&crash_memory_rgns, &crash_reserved_mem)) {
+ fprintf(stderr,
+ "Error: Number of crash memory ranges excedeed the max limit\n");
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /*
+ * Make sure that the memory regions are sorted.
+ */
+ mem_regions_sort(&crash_memory_rgns);
+
+ dbgprint_mem_range("Coredump memory ranges",
+ crash_memory_rgns.ranges, crash_memory_rgns.size);
+
return 0;
}
diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
index f33c7a25b454..07a0ed0bc344 100644
--- a/kexec/arch/arm64/crashdump-arm64.h
+++ b/kexec/arch/arm64/crashdump-arm64.h
@@ -1,12 +1,22 @@
/*
* ARM64 crashdump.
+ *
+ * Copyright (c) 2014-2016 Linaro Limited
+ * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*/
-#if !defined(CRASHDUMP_ARM64_H)
+#ifndef CRASHDUMP_ARM64_H
#define CRASHDUMP_ARM64_H
#include "kexec.h"
+#define CRASH_MAX_MEMORY_RANGES 32
+
extern struct memory_ranges usablemem_rgns;
+extern struct memory_range crash_reserved_mem;
-#endif
+#endif /* CRASHDUMP_ARM64_H */
diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h
index 7fd66eb063e1..20cda87dbd02 100644
--- a/kexec/arch/arm64/iomem.h
+++ b/kexec/arch/arm64/iomem.h
@@ -2,6 +2,7 @@
#define IOMEM_H
#define SYSTEM_RAM "System RAM\n"
+#define CRASH_KERNEL "Crash kernel\n"
#define IOMEM_RESERVED "reserved\n"
#endif
--
2.9.3

140
SOURCES/kexec-tools-2.0.14-arm64-kdump-set-up-kernel-image-segment.patch

@ -0,0 +1,140 @@ @@ -0,0 +1,140 @@
From af338a51df9012f1b1dca87ddd27a5c66db5b80b Mon Sep 17 00:00:00 2001
Message-Id: <af338a51df9012f1b1dca87ddd27a5c66db5b80b.1489676829.git.panand@redhat.com>
In-Reply-To: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
References: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Date: Wed, 15 Mar 2017 18:38:21 +0900
Subject: [PATCH 07/10] arm64: kdump: set up kernel image segment

On arm64, we can use the same kernel image as 1st kernel, but
we have to modify the entry point as well as segments' addresses
in the kernel's elf header in order to load them into correct places.

Minor conflicts was resolved in kexec/arch/arm64/crashdump-arm64.c because
get_crash_kernel_load_range() is not yet backported.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
kexec/arch/arm64/crashdump-arm64.c | 23 +++++++++++++++++++++++
kexec/arch/arm64/crashdump-arm64.h | 1 +
kexec/arch/arm64/kexec-arm64.c | 25 ++++++++++++++++++++-----
kexec/arch/arm64/kexec-elf-arm64.c | 10 +++++++++-
4 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
index 83461312d412..9517329e1086 100644
--- a/kexec/arch/arm64/crashdump-arm64.c
+++ b/kexec/arch/arm64/crashdump-arm64.c
@@ -213,3 +213,26 @@ int load_crashdump_segments(struct kexec_info *info)
return 0;
}
+
+/*
+ * e_entry and p_paddr are actually in virtual address space.
+ * Those values will be translated to physcal addresses by
+ * using virt_to_phys().
+ * So let's get ready for later use so the memory base (phys_offset)
+ * will be correctly replaced with crash_reserved_mem.start.
+ */
+void modify_ehdr_for_crashdump(struct mem_ehdr *ehdr)
+{
+ struct mem_phdr *phdr;
+ int i;
+
+ ehdr->e_entry += - arm64_mem.phys_offset + crash_reserved_mem.start;
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ phdr = &ehdr->e_phdr[i];
+ if (phdr->p_type != PT_LOAD)
+ continue;
+ phdr->p_paddr +=
+ (-arm64_mem.phys_offset + crash_reserved_mem.start);
+ }
+}
diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
index da75a2d0c5f1..382f57154f2a 100644
--- a/kexec/arch/arm64/crashdump-arm64.h
+++ b/kexec/arch/arm64/crashdump-arm64.h
@@ -21,5 +21,6 @@ extern struct memory_range crash_reserved_mem;
extern struct memory_range elfcorehdr_mem;
extern int load_crashdump_segments(struct kexec_info *info);
+extern void modify_ehdr_for_crashdump(struct mem_ehdr *ehdr);
#endif /* CRASHDUMP_ARM64_H */
diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index d02b9dac3d33..5a1da2ec1a34 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -307,12 +307,27 @@ unsigned long arm64_locate_kernel_segment(struct kexec_info *info)
{
unsigned long hole;
- hole = locate_hole(info,
- arm64_mem.text_offset + arm64_mem.image_size,
- MiB(2), 0, ULONG_MAX, 1);
+ if (info->kexec_flags & KEXEC_ON_CRASH) {
+ unsigned long hole_end;
+
+ hole = (crash_reserved_mem.start < mem_min ?
+ mem_min : crash_reserved_mem.start);
+ hole = _ALIGN_UP(hole, MiB(2));
+ hole_end = hole + arm64_mem.text_offset + arm64_mem.image_size;
+
+ if ((hole_end > mem_max) ||
+ (hole_end > crash_reserved_mem.end)) {
+ dbgprintf("%s: Crash kernel out of range\n", __func__);
+ hole = ULONG_MAX;
+ }
+ } else {
+ hole = locate_hole(info,
+ arm64_mem.text_offset + arm64_mem.image_size,
+ MiB(2), 0, ULONG_MAX, 1);
- if (hole == ULONG_MAX)
- dbgprintf("%s: locate_hole failed\n", __func__);
+ if (hole == ULONG_MAX)
+ dbgprintf("%s: locate_hole failed\n", __func__);
+ }
return hole;
}
diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
index c70a37ae7732..842ce21e2387 100644
--- a/kexec/arch/arm64/kexec-elf-arm64.c
+++ b/kexec/arch/arm64/kexec-elf-arm64.c
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <linux/elf.h>
+#include "crashdump-arm64.h"
#include "kexec-arm64.h"
#include "kexec-elf.h"
#include "kexec-syscall.h"
@@ -105,7 +106,8 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
}
arm64_mem.vp_offset = _ALIGN_DOWN(ehdr.e_entry, MiB(2));
- arm64_mem.vp_offset -= kernel_segment - get_phys_offset();
+ if (!(info->kexec_flags & KEXEC_ON_CRASH))
+ arm64_mem.vp_offset -= kernel_segment - get_phys_offset();
dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment);
dbgprintf("%s: text_offset: %016lx\n", __func__,
@@ -127,6 +129,12 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
__func__);
goto exit;
}
+
+ /*
+ * offset addresses in order to fit vmlinux
+ * (elf_exec) into crash kernel's memory
+ */
+ modify_ehdr_for_crashdump(&ehdr);
}
/* load the kernel */
--
2.9.3

35
SOURCES/kexec-tools-2.0.14-arm64-kdump-set-up-other-segments.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
From 6b1b954c9b2faf4969fa9f285d4162bd41b78498 Mon Sep 17 00:00:00 2001
Message-Id: <6b1b954c9b2faf4969fa9f285d4162bd41b78498.1489676829.git.panand@redhat.com>
In-Reply-To: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
References: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Date: Wed, 15 Mar 2017 18:38:22 +0900
Subject: [PATCH 08/10] arm64: kdump: set up other segments

We make sure that all the other segments, initrd and device-tree blob,
also be loaded into the reserved memory of crash dump kernel.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
kexec/arch/arm64/kexec-arm64.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 5a1da2ec1a34..5e30107b043f 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -375,7 +375,10 @@ int arm64_load_other_segments(struct kexec_info *info,
/* Put the other segments after the image. */
hole_min = image_base + arm64_mem.image_size;
- hole_max = ULONG_MAX;
+ if (info->kexec_flags & KEXEC_ON_CRASH)
+ hole_max = crash_reserved_mem.end;
+ else
+ hole_max = ULONG_MAX;
if (arm64_opts.initrd) {
initrd_buf = slurp_file(arm64_opts.initrd, &initrd_size);
--
2.9.3

43
SOURCES/kexec-tools-2.0.14-build_mem_phdrs-check-if-p_paddr-is-invalid.patch

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
From 5520739f1e6e31c7731d34d384bbaf4904282931 Mon Sep 17 00:00:00 2001
Message-Id: <5520739f1e6e31c7731d34d384bbaf4904282931.1489470510.git.panand@redhat.com>
From: Pratyush Anand <panand@redhat.com>
Date: Wed, 1 Mar 2017 11:19:42 +0530
Subject: [PATCH] build_mem_phdrs(): check if p_paddr is invalid

Currently, all the p_paddr of PT_LOAD headers are assigned to 0, which
is not correct and could be misleading, since 0 is a valid physical
address.

Upstream kernel commit "464920104bf7 /proc/kcore: update physical
address for kcore ram and text" fixed it and now invalid PT_LOAD is
assigned as -1.

kexec/arch/i386/crashdump-x86.c:get_kernel_vaddr_and_size() uses kcore
interface and so calls build_mem_phdrs() for kcore PT_LOAD headers.

This patch fixes build_mem_phdrs() to check if p_paddr is invalid.

Signed-off-by: Pratyush Anand <panand@redhat.com>
Acked-by: Dave Young <dyoung@redhat.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
kexec/kexec-elf.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kexec/kexec-elf.c b/kexec/kexec-elf.c
index 1d6320a2f0e6..be60bbd48486 100644
--- a/kexec/kexec-elf.c
+++ b/kexec/kexec-elf.c
@@ -432,7 +432,8 @@ static int build_mem_phdrs(const char *buf, off_t len, struct mem_ehdr *ehdr,
}
return -1;
}
- if ((phdr->p_paddr + phdr->p_memsz) < phdr->p_paddr) {
+ if (phdr->p_paddr != (unsigned long long)-1 &&
+ (phdr->p_paddr + phdr->p_memsz) < phdr->p_paddr) {
/* The memory address wraps */
if (probe_debug) {
fprintf(stderr, "ELF address wrap around\n");
--
2.9.3

32
SOURCES/kexec-tools-2.0.14-kexec-Increase-the-upper-limit-for-RAM-segments.patch

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
From 24aa2d93cac316657a2c20f28b8687bbf7e22991 Mon Sep 17 00:00:00 2001
Message-Id: <24aa2d93cac316657a2c20f28b8687bbf7e22991.1492785094.git.panand@redhat.com>
From: Sameer Goel <sgoel@codeaurora.org>
Date: Wed, 18 Jan 2017 16:15:12 -0700
Subject: [PATCH] kexec: Increase the upper limit for RAM segments

On a newer UEFI based Qualcomm target the number of system ram regions
retrieved from /proc/iomem are ~40. So increasing the current hardcoded
values to 64 from 16.

Signed-off-by: Sameer Goel <sgoel@codeaurora.org>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
kexec/arch/arm64/kexec-arm64.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
index bac62f8b19e0..bd4c20e76d15 100644
--- a/kexec/arch/arm64/kexec-arm64.h
+++ b/kexec/arch/arm64/kexec-arm64.h
@@ -11,7 +11,7 @@
#include "image-header.h"
#include "kexec.h"
-#define KEXEC_SEGMENT_MAX 16
+#define KEXEC_SEGMENT_MAX 64
#define BOOT_BLOCK_VERSION 17
#define BOOT_BLOCK_LAST_COMP_VERSION 16
--
2.9.3

79
SOURCES/kexec-tools-2.0.14-kexec-exntend-the-semantics-of-kexec_iomem_for_each_.patch

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
From e7bb07ee7b499f71990e9e83596bdb2ddabdd4cd Mon Sep 17 00:00:00 2001
Message-Id: <e7bb07ee7b499f71990e9e83596bdb2ddabdd4cd.1489676829.git.panand@redhat.com>
In-Reply-To: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
References: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
From: AKASHI Takahiro <takahiro.akashi@linaro.org>
Date: Wed, 15 Mar 2017 18:38:16 +0900
Subject: [PATCH 02/10] kexec: exntend the semantics of
kexec_iomem_for_each_line

The current kexec_iomem_for_each_line() counts up all the lines for which
a callback function returns zero(0) or positive, and otherwise it stops
further scanning.
This behavior is incovenient in some cases. For instance, on arm64, we want
to count up "System RAM" entries, but need to skip "reserved" entries.

So this patch extends the semantics so that we will continue to scan
succeeding entries but not count lines for which a callback function
returns positive.

The current users of kexec_iomem_for_each_line(), arm, sh and x86, will not
be affected by this change because
* arm
The callback function only returns -1 or 0, and the return value of
kexec_iomem_for_each_line() will never be used.
* sh, x86
The callback function may return (-1 for sh,) 0 or 1, but always returns
1 once we have reached the maximum number of entries allowed.
Even so the current kexec_iomem_for_each_line() counts them up.
This change actually fixes this bug.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
kexec/kexec-iomem.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/kexec/kexec-iomem.c b/kexec/kexec-iomem.c
index 485a2e810080..0a0277a422d8 100644
--- a/kexec/kexec-iomem.c
+++ b/kexec/kexec-iomem.c
@@ -18,6 +18,9 @@
* Iterate over each line in the file returned by proc_iomem(). If match is
* NULL or if the line matches with our match-pattern then call the
* callback if non-NULL.
+ * If match is NULL, callback should return a negative if error.
+ * Otherwise the interation goes on, incrementing nr but only if callback
+ * returns 0 (matched).
*
* Return the number of lines matched.
*/
@@ -37,7 +40,7 @@ int kexec_iomem_for_each_line(char *match,
char *str;
int consumed;
int count;
- int nr = 0;
+ int nr = 0, ret;
fp = fopen(iomem, "r");
if (!fp)
@@ -50,11 +53,13 @@ int kexec_iomem_for_each_line(char *match,
str = line + consumed;
size = end - start + 1;
if (!match || memcmp(str, match, strlen(match)) == 0) {
- if (callback
- && callback(data, nr, str, start, size) < 0) {
- break;
+ if (callback) {
+ ret = callback(data, nr, str, start, size);
+ if (ret < 0)
+ break;
+ else if (ret == 0)
+ nr++;
}
- nr++;
}
}
--
2.9.3

187
SOURCES/kexec-tools-2.0.14-kexec-generalize-and-rename-get_kernel_stext_sym.patch

@ -0,0 +1,187 @@ @@ -0,0 +1,187 @@
From d8e8090a66891eb114f31ed0d4c006a161efc109 Mon Sep 17 00:00:00 2001
Message-Id: <d8e8090a66891eb114f31ed0d4c006a161efc109.1489676829.git.panand@redhat.com>
In-Reply-To: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
References: <f85183096d31d865c97565614535d84943b12908.1489676829.git.panand@redhat.com>
From: Pratyush Anand <panand@redhat.com>
Date: Wed, 15 Mar 2017 18:38:17 +0900
Subject: [PATCH 03/10] kexec: generalize and rename get_kernel_stext_sym()

get_kernel_stext_sym() has been defined for both arm and i386. Other
architecture might need some other kernel symbol address. Therefore rewrite
this function as generic function to get any kernel symbol address.

More over, kallsyms is not arch specific representation, therefore have
common function for all arches.

Signed-off-by: Pratyush Anand <panand@redhat.com>
[created symbols.c]
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
kexec/Makefile | 1 +
kexec/arch/arm/crashdump-arm.c | 40 +---------------------------------------
kexec/arch/i386/crashdump-x86.c | 29 -----------------------------
kexec/kexec.h | 2 ++
kexec/symbols.c | 34 ++++++++++++++++++++++++++++++++++
5 files changed, 38 insertions(+), 68 deletions(-)
create mode 100644 kexec/symbols.c

diff --git a/kexec/Makefile b/kexec/Makefile
index 39f365f543d7..2b4fb3d162ec 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -26,6 +26,7 @@ KEXEC_SRCS_base += kexec/kernel_version.c
KEXEC_SRCS_base += kexec/lzma.c
KEXEC_SRCS_base += kexec/zlib.c
KEXEC_SRCS_base += kexec/kexec-xen.c
+KEXEC_SRCS_base += kexec/symbols.c
KEXEC_GENERATED_SRCS += $(PURGATORY_HEX_C)
diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 4a89b5ea9645..245c21af5e32 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -73,48 +73,10 @@ static struct crash_elf_info elf_info = {
extern unsigned long long user_page_offset;
-/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */
-static unsigned long long get_kernel_stext_sym(void)
-{
- const char *kallsyms = "/proc/kallsyms";
- const char *stext = "_stext";
- char sym[128];
- char line[128];
- FILE *fp;
- unsigned long long vaddr = 0;
- char type;
-
- fp = fopen(kallsyms, "r");
- if (!fp) {
- fprintf(stderr, "Cannot open %s\n", kallsyms);
- return 0;
- }
-
- while(fgets(line, sizeof(line), fp) != NULL) {
- unsigned long long addr;
-
- if (sscanf(line, "%Lx %c %s", &addr, &type, sym) != 3)
- continue;
-
- if (strcmp(sym, stext) == 0) {
- dbgprintf("kernel symbol %s vaddr = %#llx\n", stext, addr);
- vaddr = addr;
- break;
- }
- }
-
- fclose(fp);
-
- if (vaddr == 0)
- fprintf(stderr, "Cannot get kernel %s symbol address\n", stext);
-
- return vaddr;
-}
-
static int get_kernel_page_offset(struct kexec_info *info,
struct crash_elf_info *elf_info)
{
- unsigned long long stext_sym_addr = get_kernel_stext_sym();
+ unsigned long long stext_sym_addr = get_kernel_sym("_stext");
if (stext_sym_addr == 0) {
if (user_page_offset != (-1ULL)) {
elf_info->page_offset = user_page_offset;
diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index c4cf2013a001..a324c6c9074f 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -102,35 +102,6 @@ static int get_kernel_paddr(struct kexec_info *UNUSED(info),
return -1;
}
-/* Retrieve kernel symbol virtual address from /proc/kallsyms */
-static unsigned long long get_kernel_sym(const char *symbol)
-{
- const char *kallsyms = "/proc/kallsyms";
- char sym[128];
- char line[128];
- FILE *fp;
- unsigned long long vaddr;
- char type;
-
- fp = fopen(kallsyms, "r");
- if (!fp) {
- fprintf(stderr, "Cannot open %s\n", kallsyms);
- return 0;
- }
-
- while(fgets(line, sizeof(line), fp) != NULL) {
- if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
- continue;
- if (strcmp(sym, symbol) == 0) {
- dbgprintf("kernel symbol %s vaddr = %16llx\n", symbol, vaddr);
- return vaddr;
- }
- }
-
- dbgprintf("Cannot get kernel %s symbol address\n", symbol);
- return 0;
-}
-
/* Retrieve info regarding virtual address kernel has been compiled for and
* size of the kernel from /proc/kcore. Current /proc/kcore parsing from
* from kexec-tools fails because of malformed elf notes. A kernel patch has
diff --git a/kexec/kexec.h b/kexec/kexec.h
index 9194f1c87c91..b4fafad9487b 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -312,4 +312,6 @@ int xen_kexec_load(struct kexec_info *info);
int xen_kexec_unload(uint64_t kexec_flags);
void xen_kexec_exec(void);
+extern unsigned long long get_kernel_sym(const char *text);
+
#endif /* KEXEC_H */
diff --git a/kexec/symbols.c b/kexec/symbols.c
new file mode 100644
index 000000000000..5e42de98de32
--- /dev/null
+++ b/kexec/symbols.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+#include <string.h>
+#include "kexec.h"
+
+/* Retrieve kernel symbol virtual address from /proc/kallsyms */
+unsigned long long get_kernel_sym(const char *symbol)
+{
+ const char *kallsyms = "/proc/kallsyms";
+ char sym[128];
+ char line[128];
+ FILE *fp;
+ unsigned long long vaddr;
+ char type;
+
+ fp = fopen(kallsyms, "r");
+ if (!fp) {
+ fprintf(stderr, "Cannot open %s\n", kallsyms);
+ return 0;
+ }
+
+ while (fgets(line, sizeof(line), fp) != NULL) {
+ if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
+ continue;
+ if (strcmp(sym, symbol) == 0) {
+ dbgprintf("kernel symbol %s vaddr = %16llx\n",
+ symbol, vaddr);
+ return vaddr;
+ }
+ }
+
+ dbgprintf("Cannot get kernel %s symbol address\n", symbol);
+
+ return 0;
+}
--
2.9.3

94
SOURCES/kexec-tools-2.0.14-kexec-powerpc-fix-command-line-overflow-error.patch

@ -0,0 +1,94 @@ @@ -0,0 +1,94 @@
From 21eb397a5fc9227cd95d23e8c74a49cf6a293e57 Mon Sep 17 00:00:00 2001

From: Hari Bathini <hbathini@linux.vnet.ibm.com>

Subject: [PATCH] kexec-tools: powerpc: fix command line overflow error

Since kernel commit a5980d064fe2 ("powerpc: Bump COMMAND_LINE_SIZE
to 2048"), powerpc bumped command line size to 2048 but the size
used here is still the default value of 512. Bump it to 2048 to
fix command line overflow errors observed when command line length
is above 512 bytes. Also, get rid of the multiple definitions of
COMMAND_LINE_SIZE macro in ppc architecture.

Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
kexec/arch/ppc/crashdump-powerpc.h | 2 --
kexec/arch/ppc/fs2dt.c | 1 -
kexec/arch/ppc/kexec-ppc.h | 3 ++-
kexec/arch/ppc/ops.h | 1 -
kexec/arch/ppc64/crashdump-ppc64.h | 2 +-
5 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/kexec/arch/ppc/crashdump-powerpc.h b/kexec/arch/ppc/crashdump-powerpc.h
index 9b9b01e..97b5095 100644
--- a/kexec/arch/ppc/crashdump-powerpc.h
+++ b/kexec/arch/ppc/crashdump-powerpc.h
@@ -20,8 +20,6 @@ extern struct arch_options_t arch_options;
#define KERNELBASE PAGE_OFFSET
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
-#define COMMAND_LINE_SIZE 512 /* from kernel */
-
#ifdef CONFIG_BOOKE
/* We don't need backup region in Book E */
#define BACKUP_SRC_START 0x0000
diff --git a/kexec/arch/ppc/fs2dt.c b/kexec/arch/ppc/fs2dt.c
index 6e77379..fed499b 100644
--- a/kexec/arch/ppc/fs2dt.c
+++ b/kexec/arch/ppc/fs2dt.c
@@ -37,7 +37,6 @@
#define TREEWORDS 65536 /* max 32 bit words for properties */
#define MEMRESERVE 256 /* max number of reserved memory blks */
#define MAX_MEMORY_RANGES 1024
-#define COMMAND_LINE_SIZE 512 /* from kernel */
static char pathname[MAXPATH];
static char propnames[NAMESPACE] = { 0 };
diff --git a/kexec/arch/ppc/kexec-ppc.h b/kexec/arch/ppc/kexec-ppc.h
index 904cf48..6dc36c6 100644
--- a/kexec/arch/ppc/kexec-ppc.h
+++ b/kexec/arch/ppc/kexec-ppc.h
@@ -6,6 +6,8 @@
#define CORE_TYPE_ELF32 1
#define CORE_TYPE_ELF64 2
+#define COMMAND_LINE_SIZE 2048 /* from kernel */
+
extern unsigned char setup_simple_start[];
extern uint32_t setup_simple_size;
@@ -75,7 +77,6 @@ extern unsigned long dt_address_cells, dt_size_cells;
extern int init_memory_region_info(void);
extern int read_memory_region_limits(int fd, unsigned long long *start,
unsigned long long *end);
-#define COMMAND_LINE_SIZE 512 /* from kernel */
/*fs2dt*/
void reserve(unsigned long long where, unsigned long long length);
diff --git a/kexec/arch/ppc/ops.h b/kexec/arch/ppc/ops.h
index 7334a05..5e7a070 100644
--- a/kexec/arch/ppc/ops.h
+++ b/kexec/arch/ppc/ops.h
@@ -12,7 +12,6 @@
#define _PPC_BOOT_OPS_H_
#include "types.h"
-#define COMMAND_LINE_SIZE 512
#define MAX_PATH_LEN 256
#define MAX_PROP_LEN 256 /* What should this be? */
diff --git a/kexec/arch/ppc64/crashdump-ppc64.h b/kexec/arch/ppc64/crashdump-ppc64.h
index d654c6b..42ccc31 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.h
+++ b/kexec/arch/ppc64/crashdump-ppc64.h
@@ -16,7 +16,7 @@ void add_usable_mem_rgns(unsigned long long base, unsigned long long size);
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define MAXMEM (-KERNELBASE-VMALLOCBASE)
-#define COMMAND_LINE_SIZE 512 /* from kernel */
+#define COMMAND_LINE_SIZE 2048 /* from kernel */
/* Backup Region, First 64K of System RAM. */
#define BACKUP_SRC_START 0x0000
#define BACKUP_SRC_END 0xffff

47
SOURCES/kexec-tools-2.0.14-makedumpfile-elf_info-kcore-check-for-invalid-physic.patch

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
From f4ab6897a716d3f3959f6cb8cab27744eaecb5a6 Mon Sep 17 00:00:00 2001
Message-Id: <f4ab6897a716d3f3959f6cb8cab27744eaecb5a6.1489471500.git.panand@redhat.com>
In-Reply-To: <4b0bed3523a5f6c2c428d9dab3d27d4572207d52.1489471500.git.panand@redhat.com>
References: <4b0bed3523a5f6c2c428d9dab3d27d4572207d52.1489471500.git.panand@redhat.com>
From: Pratyush Anand <panand@redhat.com>
Date: Thu, 2 Mar 2017 17:37:16 +0900
Subject: [PATCH 4/7] [PATCH v3 4/7] elf_info: kcore: check for invalid
physical address

kcore passes correct phys_start for direct mapped region and an invalid
value (-1) for all other regions after the kernel commit
464920104bf7(/proc/kcore: update physical address for kcore ram and
text). arch specific function is_phys_addr() accepts only virt_start.
Therefore, check for valid phys_start in get_kcore_dump_loads().

Signed-off-by: Pratyush Anand <panand@redhat.com>
---
elf_info.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/makedumpfile-1.6.1/elf_info.c b/makedumpfile-1.6.1/elf_info.c
index 65ff333cf33a..c5743b3cab28 100644
--- a/makedumpfile-1.6.1/elf_info.c
+++ b/makedumpfile-1.6.1/elf_info.c
@@ -881,7 +881,8 @@ int get_kcore_dump_loads(void)
for (i = 0; i < num_pt_loads; ++i) {
struct pt_load_segment *p = &pt_loads[i];
- if (!is_phys_addr(p->virt_start))
+ if (p->phys_start == NOT_PADDR
+ || !is_phys_addr(p->virt_start))
continue;
loads++;
}
@@ -901,7 +902,8 @@ int get_kcore_dump_loads(void)
for (i = 0, j = 0; i < num_pt_loads; ++i) {
struct pt_load_segment *p = &pt_loads[i];
- if (!is_phys_addr(p->virt_start))
+ if (p->phys_start == NOT_PADDR
+ || !is_phys_addr(p->virt_start))
continue;
if (j >= loads)
return FALSE;
--
2.9.3

47
SOURCES/kexec-tools-2.0.14-makedumpfile-initial-call-cache_init-a-bit-early.patch

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
From 8e2834bac4f62da3894da297f083068431be6d80 Mon Sep 17 00:00:00 2001
Message-Id: <8e2834bac4f62da3894da297f083068431be6d80.1489471500.git.panand@redhat.com>
In-Reply-To: <4b0bed3523a5f6c2c428d9dab3d27d4572207d52.1489471500.git.panand@redhat.com>
References: <4b0bed3523a5f6c2c428d9dab3d27d4572207d52.1489471500.git.panand@redhat.com>
From: Pratyush Anand <panand@redhat.com>
Date: Thu, 2 Mar 2017 17:37:11 +0900
Subject: [PATCH 2/7] [PATCH v3 2/7] initial(): call cache_init() a bit early

Call cache_init() before get_kcore_dump_loads(), because latter uses
cache_search().

Call path is like this :
get_kcore_dump_loads() -> process_dump_load() -> vaddr_to_paddr() ->
vtop4_x86_64() -> readmem() -> cache_search()

Signed-off-by: Pratyush Anand <panand@redhat.com>
---
makedumpfile.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/makedumpfile-1.6.1/makedumpfile.c b/makedumpfile-1.6.1/makedumpfile.c
index 6942047199de..3b8e9810468d 100644
--- a/makedumpfile-1.6.1/makedumpfile.c
+++ b/makedumpfile-1.6.1/makedumpfile.c
@@ -3878,6 +3878,9 @@ initial(void)
if (!get_value_for_old_linux())
return FALSE;
+ if (!is_xen_memory() && !cache_init())
+ return FALSE;
+
if (info->flag_mem_usage && !get_kcore_dump_loads())
return FALSE;
@@ -4000,9 +4003,6 @@ out:
}
}
- if (!is_xen_memory() && !cache_init())
- return FALSE;
-
if (debug_info && !get_machdep_info())
return FALSE;
--
2.9.3

45
SOURCES/kexec-tools-2.0.14-makedumpfile-makedumpfile-Correct-the-calculation-of.patch

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
From 4c53423b995463067fbbd394e724b4d1d6ea3d62 Mon Sep 17 00:00:00 2001
Message-Id: <4c53423b995463067fbbd394e724b4d1d6ea3d62.1489471500.git.panand@redhat.com>
In-Reply-To: <4b0bed3523a5f6c2c428d9dab3d27d4572207d52.1489471500.git.panand@redhat.com>
References: <4b0bed3523a5f6c2c428d9dab3d27d4572207d52.1489471500.git.panand@redhat.com>
From: Baoquan He <bhe@redhat.com>
Date: Thu, 2 Mar 2017 17:37:19 +0900
Subject: [PATCH 5/7] [PATCH v3 5/7] makedumpfile: Correct the calculation of
kvaddr in set_kcore_vmcoreinfo

In set_kcore_vmcoreinfo, we calculate the virtual address of vmcoreinfo
by OR operation as below:

kvaddr = (ulong)vmcoreinfo_addr | PAGE_OFFSET;

When mm sections kaslr is not enabled, this is correct since the
starting address of direct mapping section is 0xffff880000000000 which
is 1T aligned. Usually system with memory below 1T won't cause problem.

However with mm section kaslr enabled, the starting address of direct
mapping is 1G aligned. The above code makes kvaddr unsure.

So change it to adding operation:
kvaddr = (ulong)vmcoreinfo_addr + PAGE_OFFSET;

Signed-off-by: Baoquan He <bhe@redhat.com>
---
elf_info.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/makedumpfile-1.6.1/elf_info.c b/makedumpfile-1.6.1/elf_info.c
index c5743b3cab28..100272f83c48 100644
--- a/makedumpfile-1.6.1/elf_info.c
+++ b/makedumpfile-1.6.1/elf_info.c
@@ -372,7 +372,7 @@ int set_kcore_vmcoreinfo(uint64_t vmcoreinfo_addr, uint64_t vmcoreinfo_len)
off_t offset_desc;
offset = UNINITIALIZED;
- kvaddr = (ulong)vmcoreinfo_addr | PAGE_OFFSET;
+ kvaddr = (ulong)vmcoreinfo_addr + PAGE_OFFSET;
for (i = 0; i < num_pt_loads; ++i) {
struct pt_load_segment *p = &pt_loads[i];
--
2.9.3

57
SOURCES/kexec-tools-2.0.14-makedumpfile-makedumpfile-Discard-process_dump_load.patch

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
From f3ff8c6232de43fa2cc60f5ca0f233cf8eb8d2ad Mon Sep 17 00:00:00 2001
Message-Id: <f3ff8c6232de43fa2cc60f5ca0f233cf8eb8d2ad.1489471500.git.panand@redhat.com>
In-Reply-To: <4b0bed3523a5f6c2c428d9dab3d27d4572207d52.1489471500.git.panand@redhat.com>
References: <4b0bed3523a5f6c2c428d9dab3d27d4572207d52.1489471500.git.panand@redhat.com>
From: Baoquan He <bhe@redhat.com>
Date: Thu, 2 Mar 2017 17:37:23 +0900
Subject: [PATCH 6/7] [PATCH v3 6/7] makedumpfile: Discard process_dump_load

Kernel commit 464920104bf7 (/proc/kcore: update physical address for
kcore ram and text) provides physical address of direct mapping kcore
program segments. So no need to calculate it specifically now. And the
old code is not correct since it calls vaddr_to_paddr() which has not
been ready at that time.

Signed-off-by: Baoquan He <bhe@redhat.com>
---
elf_info.c | 17 -----------------
1 file changed, 17 deletions(-)

diff --git a/makedumpfile-1.6.1/elf_info.c b/makedumpfile-1.6.1/elf_info.c
index 100272f83c48..8e2437622141 100644
--- a/makedumpfile-1.6.1/elf_info.c
+++ b/makedumpfile-1.6.1/elf_info.c
@@ -857,22 +857,6 @@ static int exclude_segment(struct pt_load_segment **pt_loads,
return 0;
}
-static int
-process_dump_load(struct pt_load_segment *pls)
-{
- unsigned long long paddr;
-
- paddr = vaddr_to_paddr(pls->virt_start);
- pls->phys_start = paddr;
- pls->phys_end = paddr + (pls->virt_end - pls->virt_start);
- DEBUG_MSG("process_dump_load\n");
- DEBUG_MSG(" phys_start : %llx\n", pls->phys_start);
- DEBUG_MSG(" phys_end : %llx\n", pls->phys_end);
- DEBUG_MSG(" virt_start : %llx\n", pls->virt_start);
- DEBUG_MSG(" virt_end : %llx\n", pls->virt_end);
-
- return TRUE;
-}
int get_kcore_dump_loads(void)
{
@@ -917,7 +901,6 @@ int get_kcore_dump_loads(void)
}
pls[j] = *p;
- process_dump_load(&pls[j]);
j++;
}
--
2.9.3

303
SOURCES/kexec-tools-2.0.14-makedumpfile-makedumpfile-add-runtime-kaslr-offset-if-it-exists.patch

@ -0,0 +1,303 @@ @@ -0,0 +1,303 @@
From 302c16ede3723264ca0abb5eef9c9f553ffcfbd7 Mon Sep 17 00:00:00 2001
Message-Id: <302c16ede3723264ca0abb5eef9c9f553ffcfbd7.1496033260.git.panand@redhat.com>
From: Pratyush Anand <panand@redhat.com>
Date: Wed, 26 Apr 2017 14:36:29 +0530
Subject: [PATCH 1/3] makedumpfile: add runtime kaslr offset if it exists

If we have to erase a symbol from vmcore whose address is not present in
vmcoreinfo, then we need to pass vmlinux as well to get the symbol
address.
When kaslr is enabled, virtual address of all the kernel symbols are
randomized with an offset. vmlinux always has a static address, but all
the arch specific calculation are based on run time kernel address. So
we need to find a way to translate symbol address from vmlinux to kernel
run time address.

without this patch:
# cat > scrub.conf << EOF
[vmlinux]
erase jiffies
erase init_task.utime
for tsk in init_task.tasks.next within task_struct:tasks
erase tsk.utime
endfor
EOF

# makedumpfile --split -d 5 -x vmlinux --config scrub.conf vmcore dumpfile_{1,2,3}

readpage_kdump_compressed: pfn(f97ea) is excluded from vmcore.
readmem: type_addr: 1, addr:f97eaff8, size:8
vtop4_x86_64: Can't get pml4 (page_dir:f97eaff8).
readmem: Can't convert a virtual address(ffffffff819f1284) to physical address.
readmem: type_addr: 0, addr:ffffffff819f1284, size:390
check_release: Can't get the address of system_utsname.

After this patch check_release() is ok, and also we are able to erase
symbol from vmcore.

Signed-off-by: Pratyush Anand <panand@redhat.com>
---
arch/x86_64.c | 36 ++++++++++++++++++++++++++++++++++++
erase_info.c | 1 +
makedumpfile.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
makedumpfile.h | 16 ++++++++++++++++
4 files changed, 99 insertions(+)

diff --git a/makedumpfile-1.6.1/arch/x86_64.c b/makedumpfile-1.6.1/arch/x86_64.c
index e978a36f8878..fd2e8ac154d6 100644
--- a/makedumpfile-1.6.1/arch/x86_64.c
+++ b/makedumpfile-1.6.1/arch/x86_64.c
@@ -33,6 +33,42 @@ get_xen_p2m_mfn(void)
return NOT_FOUND_LONG_VALUE;
}
+unsigned long
+get_kaslr_offset_x86_64(unsigned long vaddr)
+{
+ unsigned int i;
+ char buf[BUFSIZE_FGETS], *endp;
+
+ if (!info->kaslr_offset && info->file_vmcoreinfo) {
+ if (fseek(info->file_vmcoreinfo, 0, SEEK_SET) < 0) {
+ ERRMSG("Can't seek the vmcoreinfo file(%s). %s\n",
+ info->name_vmcoreinfo, strerror(errno));
+ return FALSE;
+ }
+
+ while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) {
+ i = strlen(buf);
+ if (!i)
+ break;
+ if (buf[i - 1] == '\n')
+ buf[i - 1] = '\0';
+ if (strncmp(buf, STR_KERNELOFFSET,
+ strlen(STR_KERNELOFFSET)) == 0)
+ info->kaslr_offset =
+ strtoul(buf+strlen(STR_KERNELOFFSET),&endp,16);
+ }
+ }
+ if (vaddr >= __START_KERNEL_map &&
+ vaddr < __START_KERNEL_map + info->kaslr_offset)
+ return info->kaslr_offset;
+ else
+ /*
+ * TODO: we need to check if it is vmalloc/vmmemmap/module
+ * address, we will have different offset
+ */
+ return 0;
+}
+
static int
get_page_offset_x86_64(void)
{
diff --git a/makedumpfile-1.6.1/erase_info.c b/makedumpfile-1.6.1/erase_info.c
index f2ba9149e93e..60abfa1a1adf 100644
--- a/makedumpfile-1.6.1/erase_info.c
+++ b/makedumpfile-1.6.1/erase_info.c
@@ -1088,6 +1088,7 @@ resolve_config_entry(struct config_entry *ce, unsigned long long base_vaddr,
ce->line, ce->name);
return FALSE;
}
+ ce->sym_addr += get_kaslr_offset(ce->sym_addr);
ce->type_name = get_symbol_type_name(ce->name,
DWARF_INFO_GET_SYMBOL_TYPE,
&ce->size, &ce->type_flag);
diff --git a/makedumpfile-1.6.1/makedumpfile.c b/makedumpfile-1.6.1/makedumpfile.c
index 301772a8820c..9babf1a07154 100644
--- a/makedumpfile-1.6.1/makedumpfile.c
+++ b/makedumpfile-1.6.1/makedumpfile.c
@@ -3782,6 +3782,46 @@ free_for_parallel()
}
int
+find_kaslr_offsets()
+{
+ off_t offset;
+ unsigned long size;
+ int ret = FALSE;
+
+ get_vmcoreinfo(&offset, &size);
+
+ if (!(info->name_vmcoreinfo = strdup(FILENAME_VMCOREINFO))) {
+ MSG("Can't duplicate strings(%s).\n", FILENAME_VMCOREINFO);
+ return FALSE;
+ }
+ if (!copy_vmcoreinfo(offset, size))
+ goto out;
+
+ if (!open_vmcoreinfo("r"))
+ goto out;
+
+ unlink(info->name_vmcoreinfo);
+
+ /*
+ * This arch specific function should update info->kaslr_offset. If
+ * kaslr is not enabled then offset will be set to 0. arch specific
+ * function might need to read from vmcoreinfo, therefore we have
+ * called this function between open_vmcoreinfo() and
+ * close_vmcoreinfo()
+ */
+ get_kaslr_offset(SYMBOL(_stext));
+
+ close_vmcoreinfo();
+
+ ret = TRUE;
+out:
+ free(info->name_vmcoreinfo);
+ info->name_vmcoreinfo = NULL;
+
+ return ret;
+}
+
+int
initial(void)
{
off_t offset;
@@ -3833,6 +3873,9 @@ initial(void)
set_dwarf_debuginfo("vmlinux", NULL,
info->name_vmlinux, info->fd_vmlinux);
+ if (has_vmcoreinfo() && !find_kaslr_offsets())
+ return FALSE;
+
if (!get_symbol_info())
return FALSE;
@@ -8635,6 +8678,7 @@ close_vmcoreinfo(void)
if(fclose(info->file_vmcoreinfo) < 0)
ERRMSG("Can't close the vmcoreinfo file(%s). %s\n",
info->name_vmcoreinfo, strerror(errno));
+ info->file_vmcoreinfo = NULL;
}
void
@@ -11026,11 +11070,13 @@ main(int argc, char *argv[])
strerror(errno));
goto out;
}
+ info->file_vmcoreinfo = NULL;
info->fd_vmlinux = -1;
info->fd_xen_syms = -1;
info->fd_memory = -1;
info->fd_dumpfile = -1;
info->fd_bitmap = -1;
+ info->kaslr_offset = 0;
initialize_tables();
/*
diff --git a/makedumpfile-1.6.1/makedumpfile.h b/makedumpfile-1.6.1/makedumpfile.h
index e32e567018f6..9f16becadd55 100644
--- a/makedumpfile-1.6.1/makedumpfile.h
+++ b/makedumpfile-1.6.1/makedumpfile.h
@@ -253,10 +253,14 @@ static inline int string_exists(char *s) { return (s ? TRUE : FALSE); }
#define SYMBOL_INIT(symbol, str_symbol) \
do { \
SYMBOL(symbol) = get_symbol_addr(str_symbol); \
+ if (SYMBOL(symbol) != NOT_FOUND_SYMBOL) \
+ SYMBOL(symbol) += info->kaslr_offset; \
} while (0)
#define SYMBOL_INIT_NEXT(symbol, str_symbol) \
do { \
SYMBOL(symbol) = get_next_symbol_addr(str_symbol); \
+ if (SYMBOL(symbol) != NOT_FOUND_SYMBOL) \
+ SYMBOL(symbol) += info->kaslr_offset; \
} while (0)
#define WRITE_SYMBOL(str_symbol, symbol) \
do { \
@@ -495,6 +499,7 @@ do { \
#define STR_CONFIG_X86_PAE "CONFIG_X86_PAE=y"
#define STR_CONFIG_PGTABLE_4 "CONFIG_PGTABLE_4=y"
#define STR_CONFIG_PGTABLE_3 "CONFIG_PGTABLE_3=y"
+#define STR_KERNELOFFSET "KERNELOFFSET="
/*
* common value
@@ -838,6 +843,7 @@ int get_xen_info_arm64(void);
#define get_phys_base() get_phys_base_arm64()
#define get_machdep_info() get_machdep_info_arm64()
#define get_versiondep_info() get_versiondep_info_arm64()
+#define get_kaslr_offset(X) FALSE
#define get_xen_basic_info_arch(X) get_xen_basic_info_arm64(X)
#define get_xen_info_arch(X) get_xen_info_arm64(X)
#define is_phys_addr(X) stub_true_ul(X)
@@ -851,6 +857,7 @@ unsigned long long vaddr_to_paddr_arm(unsigned long vaddr);
#define get_phys_base() get_phys_base_arm()
#define get_machdep_info() get_machdep_info_arm()
#define get_versiondep_info() stub_true()
+#define get_kaslr_offset(X) FALSE
#define vaddr_to_paddr(X) vaddr_to_paddr_arm(X)
#define is_phys_addr(X) stub_true_ul(X)
#endif /* arm */
@@ -863,11 +870,13 @@ unsigned long long vaddr_to_paddr_x86(unsigned long vaddr);
#define get_phys_base() stub_true()
#define get_machdep_info() get_machdep_info_x86()
#define get_versiondep_info() get_versiondep_info_x86()
+#define get_kaslr_offset(X) FALSE
#define vaddr_to_paddr(X) vaddr_to_paddr_x86(X)
#define is_phys_addr(X) stub_true_ul(X)
#endif /* x86 */
#ifdef __x86_64__
+unsigned long get_kaslr_offset_x86_64(unsigned long vaddr);
int get_phys_base_x86_64(void);
int get_machdep_info_x86_64(void);
int get_versiondep_info_x86_64(void);
@@ -876,6 +885,7 @@ unsigned long long vtop4_x86_64(unsigned long vaddr);
#define get_phys_base() get_phys_base_x86_64()
#define get_machdep_info() get_machdep_info_x86_64()
#define get_versiondep_info() get_versiondep_info_x86_64()
+#define get_kaslr_offset(X) get_kaslr_offset_x86_64(X)
#define vaddr_to_paddr(X) vtop4_x86_64(X)
#define is_phys_addr(X) stub_true_ul(X)
#endif /* x86_64 */
@@ -888,6 +898,7 @@ unsigned long long vaddr_to_paddr_ppc64(unsigned long vaddr);
#define get_phys_base() stub_true()
#define get_machdep_info() get_machdep_info_ppc64()
#define get_versiondep_info() get_versiondep_info_ppc64()
+#define get_kaslr_offset(X) FALSE
#define vaddr_to_paddr(X) vaddr_to_paddr_ppc64(X)
#define is_phys_addr(X) stub_true_ul(X)
#endif /* powerpc64 */
@@ -899,6 +910,7 @@ unsigned long long vaddr_to_paddr_ppc(unsigned long vaddr);
#define get_phys_base() stub_true()
#define get_machdep_info() get_machdep_info_ppc()
#define get_versiondep_info() stub_true()
+#define get_kaslr_offset(X) FALSE
#define vaddr_to_paddr(X) vaddr_to_paddr_ppc(X)
#define is_phys_addr(X) stub_true_ul(X)
#endif /* powerpc32 */
@@ -911,6 +923,7 @@ int is_iomem_phys_addr_s390x(unsigned long addr);
#define get_phys_base() stub_true()
#define get_machdep_info() get_machdep_info_s390x()
#define get_versiondep_info() stub_true()
+#define get_kaslr_offset(X) FALSE
#define vaddr_to_paddr(X) vaddr_to_paddr_s390x(X)
#define is_phys_addr(X) is_iomem_phys_addr_s390x(X)
#endif /* s390x */
@@ -923,6 +936,7 @@ unsigned long long vaddr_to_paddr_ia64(unsigned long vaddr);
#define get_machdep_info() get_machdep_info_ia64()
#define get_phys_base() get_phys_base_ia64()
#define get_versiondep_info() stub_true()
+#define get_kaslr_offset(X) FALSE
#define vaddr_to_paddr(X) vaddr_to_paddr_ia64(X)
#define VADDR_REGION(X) (((unsigned long)(X)) >> REGION_SHIFT)
#define is_phys_addr(X) stub_true_ul(X)
@@ -1152,6 +1166,7 @@ struct DumpInfo {
int vmemmap_psize;
int vmemmap_cnt;
struct ppc64_vmemmap *vmemmap_list;
+ unsigned long kaslr_offset;
/*
* page table info for ppc64
@@ -1803,6 +1818,7 @@ struct memory_range {
struct memory_range crash_reserved_mem[CRASH_RESERVED_MEM_NR];
int crash_reserved_mem_nr;
+unsigned long read_vmcoreinfo_symbol(char *str_symbol);
int readmem(int type_addr, unsigned long long addr, void *bufptr, size_t size);
int get_str_osrelease_from_vmlinux(void);
int read_vmcoreinfo_xen(void);
--
2.9.3

83
SOURCES/kexec-tools-2.0.14-makedumpfile-sadump-set-info-page_size-before-cache_init.patch

@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
From 90cc28fc9ab0a0076bcd9120b4f791401655280d Mon Sep 17 00:00:00 2001
Message-Id: <90cc28fc9ab0a0076bcd9120b4f791401655280d.1496033260.git.panand@redhat.com>
In-Reply-To: <302c16ede3723264ca0abb5eef9c9f553ffcfbd7.1496033260.git.panand@redhat.com>
References: <302c16ede3723264ca0abb5eef9c9f553ffcfbd7.1496033260.git.panand@redhat.com>
From: "Hatayama, Daisuke" <d.hatayama@jp.fujitsu.com>
Date: Tue, 23 May 2017 02:52:51 +0000
Subject: [PATCH 3/3] sadump: set info->page_size before cache_init()

Currently, makedumpfile results in Segmentation fault on sadump dump
files as follows:

# LANG=C makedumpfile -f --message-level=31 -ld31 -x vmlinux ./sadump_vmcore sadump_vmcore-ld31
sadump: read dump device as single partition
sadump: single partition configuration
page_size : 4096
sadump: timezone information is missing
Segmentation fault

By bisect, I found that this issue is caused by the following commit
that moves invocation of cache_init() in initial() a bit early:

# git bisect bad
8e2834bac4f62da3894da297f083068431be6d80 is the first bad commit
commit 8e2834bac4f62da3894da297f083068431be6d80
Author: Pratyush Anand <panand@redhat.com>
Date: Thu Mar 2 17:37:11 2017 +0900

[PATCH v3 2/7] initial(): call cache_init() a bit early

Call cache_init() before get_kcore_dump_loads(), because latter uses
cache_search().

Call path is like this :
get_kcore_dump_loads() -> process_dump_load() -> vaddr_to_paddr() ->
vtop4_x86_64() -> readmem() -> cache_search()

Signed-off-by: Pratyush Anand <panand@redhat.com>

:100644 100644 6942047199deb09dd1fff2121e264584dbb05587 3b8e9810468de26b0d8b73d456f0bd4f3d3aa2fe M makedumpfile.c

In this timing, on sadump vmcores, info->page_size has not been
initialized yet so has 0. So, malloc() in cache_init() returns a chunk
of 0 size. A bit later, info->page_size is initialized with 4096.
Later processing on cache.c behaves assuming the chunk size is 8 *
4096. This destroys objects allocated after the chunk, resulting in
the above Segmentation fault.

To fix this issue, this commit moves setting info->page_size before
cache_init().

Signed-off-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
Cc: Pratyush Anand <panand@redhat.com>
---
makedumpfile.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/makedumpfile-1.6.1/makedumpfile.c b/makedumpfile-1.6.1/makedumpfile.c
index 9babf1a07154..2e4286c83b8f 100644
--- a/makedumpfile-1.6.1/makedumpfile.c
+++ b/makedumpfile-1.6.1/makedumpfile.c
@@ -3921,6 +3921,9 @@ initial(void)
if (!get_value_for_old_linux())
return FALSE;
+ if (info->flag_sadump && !set_page_size(sadump_page_size()))
+ return FALSE;
+
if (!is_xen_memory() && !cache_init())
return FALSE;
@@ -3949,9 +3952,6 @@ initial(void)
return FALSE;
}
- if (!set_page_size(sadump_page_size()))
- return FALSE;
-
if (!sadump_initialize_bitmap_memory())
return FALSE;
--
2.9.3

41
SOURCES/kexec-tools-2.0.14-makedumpfile-show_mem_usage-calculate-page-offset-af.patch

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
From 4b0bed3523a5f6c2c428d9dab3d27d4572207d52 Mon Sep 17 00:00:00 2001
Message-Id: <4b0bed3523a5f6c2c428d9dab3d27d4572207d52.1489471500.git.panand@redhat.com>
From: Pratyush Anand <panand@redhat.com>
Date: Thu, 2 Mar 2017 17:37:08 +0900
Subject: [PATCH 1/7] [PATCH v3 1/7] show_mem_usage(): calculate page offset
after elf load

x86_64 calculated page offset from PT_LOAD headers. Therefore call
get_page_offset() after get_elf_loads()

Signed-off-by: Pratyush Anand <panand@redhat.com>
---
makedumpfile.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/makedumpfile-1.6.1/makedumpfile.c b/makedumpfile-1.6.1/makedumpfile.c
index e69b6df9a9ee..6942047199de 100644
--- a/makedumpfile-1.6.1/makedumpfile.c
+++ b/makedumpfile-1.6.1/makedumpfile.c
@@ -10944,15 +10944,15 @@ int show_mem_usage(void)
info->dump_level = MAX_DUMP_LEVEL;
- if (!get_page_offset())
- return FALSE;
-
if (!open_files_for_creating_dumpfile())
return FALSE;
if (!get_elf_loads(info->fd_memory, info->name_memory))
return FALSE;
+ if (!get_page_offset())
+ return FALSE;
+
if (!get_sys_kernel_vmcoreinfo(&vmcoreinfo_addr, &vmcoreinfo_len))
return FALSE;
--
2.9.3

85
SOURCES/kexec-tools-2.0.14-makedumpfile-x86_64-calculate-page_offset-in-case-of-re-filtering.patch

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
From 586c58752e0e48e8ed48ba951e5b1448831bbf11 Mon Sep 17 00:00:00 2001
Message-Id: <586c58752e0e48e8ed48ba951e5b1448831bbf11.1496033260.git.panand@redhat.com>
In-Reply-To: <302c16ede3723264ca0abb5eef9c9f553ffcfbd7.1496033260.git.panand@redhat.com>
References: <302c16ede3723264ca0abb5eef9c9f553ffcfbd7.1496033260.git.panand@redhat.com>
From: Pratyush Anand <panand@redhat.com>
Date: Wed, 26 Apr 2017 11:04:07 +0530
Subject: [PATCH 2/3] x86_64: calculate page_offset in case of
re-filtering/sadump/virsh dump

we do not call get_elf_info() in case of refiltering and sadump.
Therefore, we will not have any pt_load in that case, and so we get:

get_page_offset_x86_64: Can't get any pt_load to calculate page offset.

However, we will have vmcoreinfo and vmlinux information in case of
re-filtering. So, we are able to find kaslr offset and we can get
page_offset_base address. Thus we can read the page offset as well.

If kaslr is not enabled and also we do not have valid PT_LOAD to
calculate page offset then use old method to find fixed page
offset.

In case of virsh dump virtual addresses in PT_LOAD are 0. Ignore such
addresses for the page_offset calculation.

Suggested-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
Signed-off-by: Pratyush Anand <panand@redhat.com>
---
arch/x86_64.c | 36 +++++++++++++++++++++++++++++-------
1 file changed, 29 insertions(+), 7 deletions(-)

diff --git a/makedumpfile-1.6.1/arch/x86_64.c b/makedumpfile-1.6.1/arch/x86_64.c
index fd2e8ac154d6..18384a8dd684 100644
--- a/makedumpfile-1.6.1/arch/x86_64.c
+++ b/makedumpfile-1.6.1/arch/x86_64.c
@@ -75,17 +75,39 @@ get_page_offset_x86_64(void)
int i;
unsigned long long phys_start;
unsigned long long virt_start;
+ unsigned long page_offset_base;
+
+ if (info->kaslr_offset) {
+ page_offset_base = get_symbol_addr("page_offset_base");
+ page_offset_base += info->kaslr_offset;
+ if (!readmem(VADDR, page_offset_base, &info->page_offset,
+ sizeof(info->page_offset))) {
+ ERRMSG("Can't read page_offset_base.\n");
+ return FALSE;
+ }
+ return TRUE;
+ }
- for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
- if (virt_start < __START_KERNEL_map
- && phys_start != NOT_PADDR) {
- info->page_offset = virt_start - phys_start;
- return TRUE;
+ if (get_num_pt_loads()) {
+ for (i = 0;
+ get_pt_load(i, &phys_start, NULL, &virt_start, NULL);
+ i++) {
+ if (virt_start != NOT_KV_ADDR
+ && virt_start < __START_KERNEL_map
+ && phys_start != NOT_PADDR) {
+ info->page_offset = virt_start - phys_start;
+ return TRUE;
+ }
}
}
- ERRMSG("Can't get any pt_load to calculate page offset.\n");
- return FALSE;
+ if (info->kernel_version < KERNEL_VERSION(2, 6, 27)) {
+ info->page_offset = __PAGE_OFFSET_ORIG;
+ } else {
+ info->page_offset = __PAGE_OFFSET_2_6_27;
+ }
+
+ return TRUE;
}
int
--
2.9.3

47
SOURCES/kexec-tools-2.0.14-makedumpfile-x86_64-check-physical-address-in-PT_LOA.patch

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
From f1363023b909df886eca5efcb64b78be9b8e6086 Mon Sep 17 00:00:00 2001
Message-Id: <f1363023b909df886eca5efcb64b78be9b8e6086.1489471500.git.panand@redhat.com>
In-Reply-To: <4b0bed3523a5f6c2c428d9dab3d27d4572207d52.1489471500.git.panand@redhat.com>
References: <4b0bed3523a5f6c2c428d9dab3d27d4572207d52.1489471500.git.panand@redhat.com>
From: Pratyush Anand <panand@redhat.com>
Date: Thu, 2 Mar 2017 17:37:13 +0900
Subject: [PATCH 3/7] [PATCH v3 3/7] x86_64: check physical address in PT_LOAD
for none direct mapped regions

A kcore PT_LOAD can have a section from vmalloc region. However,
physical address in that header would be invalid (-1) after kernel
commit 464920104bf7 (/proc/kcore: update physical address for kcore ram
and text). Therefore, check for valid physical address while calculating
page_offset or phys_offset.

Signed-off-by: Pratyush Anand <panand@redhat.com>
---
arch/x86_64.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/makedumpfile-1.6.1/arch/x86_64.c b/makedumpfile-1.6.1/arch/x86_64.c
index 893cd516fc8b..e978a36f8878 100644
--- a/makedumpfile-1.6.1/arch/x86_64.c
+++ b/makedumpfile-1.6.1/arch/x86_64.c
@@ -41,7 +41,8 @@ get_page_offset_x86_64(void)
unsigned long long virt_start;
for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
- if (virt_start < __START_KERNEL_map) {
+ if (virt_start < __START_KERNEL_map
+ && phys_start != NOT_PADDR) {
info->page_offset = virt_start - phys_start;
return TRUE;
}
@@ -76,7 +77,8 @@ get_phys_base_x86_64(void)
}
for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
- if (virt_start >= __START_KERNEL_map) {
+ if (virt_start >= __START_KERNEL_map
+ && phys_start != NOT_PADDR) {
info->phys_base = phys_start -
(virt_start & ~(__START_KERNEL_map));
--
2.9.3

67
SOURCES/kexec-tools-2.0.14-ppc64-Reduce-number-of-ELF-LOAD-segments.patch

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
From f63d8530b9b6a2d7e79b946e326e5a2197eb8f87 Mon Sep 17 00:00:00 2001
From: Petr Tesarik <ptesarik@suse.com>
Date: Thu, 19 Jan 2017 18:37:09 +0100
Subject: [PATCH] ppc64: Reduce number of ELF LOAD segments

The number of program header table entries (e_phnum) is an Elf64_Half,
which is a 16-bit entity, i.e. the limit is 65534 entries (one entry is
reserved for NOTE). This is a hard limit, defined by the ELF standard.
It is possible that more LMBs (Logical Memory Blocks) are needed to
represent all RAM on some machines, and this field overflows, causing
an incomplete /proc/vmcore file.

This has actually happened on a machine with 31TB of RAM and an LMB size
of 256MB.

However, since there is usually no memory hole between adjacent LMBs, the
map can be "compressed", combining multiple adjacent into a single LOAD
segment.

Signed-off-by: Petr Tesarik <ptesarik@suse.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
kexec/arch/ppc64/crashdump-ppc64.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index b3c8928..f62b159 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.c
+++ b/kexec/arch/ppc64/crashdump-ppc64.c
@@ -123,6 +123,7 @@ static void exclude_crash_region(uint64_t start, uint64_t end)
static int get_dyn_reconf_crash_memory_ranges(void)
{
uint64_t start, end;
+ uint64_t startrange, endrange;
char fname[128], buf[32];
FILE *file;
unsigned int i;
@@ -137,6 +138,7 @@ static int get_dyn_reconf_crash_memory_ranges(void)
}
fseek(file, 4, SEEK_SET);
+ startrange = endrange = 0;
for (i = 0; i < num_of_lmbs; i++) {
if ((n = fread(buf, 1, 24, file)) < 0) {
perror(fname);
@@ -162,8 +164,16 @@ static int get_dyn_reconf_crash_memory_ranges(void)
if ((flags & 0x80) || !(flags & 0x8))
continue;
- exclude_crash_region(start, end);
+ if (start != endrange) {
+ if (startrange != endrange)
+ exclude_crash_region(startrange, endrange);
+ startrange = start;
+ }
+ endrange = end;
}
+ if (startrange != endrange)
+ exclude_crash_region(startrange, endrange);
+
fclose(file);
return 0;
}
--
2.7.4

52
SOURCES/kexec-tools-2.0.14-x86-Support-large-number-of-memory-ranges.patch

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
From 4a6d67d9e938a7accf128aff23f8ad4bda67f729 Mon Sep 17 00:00:00 2001
From: Xunlei Pang <xlpang@redhat.com>
Date: Thu, 23 Mar 2017 19:16:59 +0800
Subject: [PATCH] x86: Support large number of memory ranges

We got a problem on one SGI 64TB machine, the current kexec-tools
failed to work due to the insufficient ranges(MAX_MEMORY_RANGES)
allowed which is defined as 1024(less than the ranges on the machine).
The kcore header is insufficient due to the same reason as well.

To solve this, this patch simply doubles "MAX_MEMORY_RANGES" and
"KCORE_ELF_HEADERS_SIZE".

Signed-off-by: Xunlei Pang <xlpang@redhat.com>
Tested-by: Frank Ramsay <frank.ramsay@hpe.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
kexec/arch/i386/kexec-x86.h | 2 +-
kexec/crashdump.h | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/kexec/arch/i386/kexec-x86.h b/kexec/arch/i386/kexec-x86.h
index 33df352..51855f8 100644
--- a/kexec/arch/i386/kexec-x86.h
+++ b/kexec/arch/i386/kexec-x86.h
@@ -1,7 +1,7 @@
#ifndef KEXEC_X86_H
#define KEXEC_X86_H
-#define MAX_MEMORY_RANGES 1024
+#define MAX_MEMORY_RANGES 2048
enum coretype {
CORE_TYPE_UNDEF = 0,
diff --git a/kexec/crashdump.h b/kexec/crashdump.h
index 86e1ef2..18bd691 100644
--- a/kexec/crashdump.h
+++ b/kexec/crashdump.h
@@ -7,8 +7,8 @@ extern int get_xen_vmcoreinfo(uint64_t *addr, uint64_t *len);
/* Need to find a better way to determine per cpu notes section size. */
#define MAX_NOTE_BYTES 1024
-/* Expecting ELF headers to fit in 32K. Increase it if you need more. */
-#define KCORE_ELF_HEADERS_SIZE 32768
+/* Expecting ELF headers to fit in 64K. Increase it if you need more. */
+#define KCORE_ELF_HEADERS_SIZE 65536
/* The address of the ELF header is passed to the secondary kernel
* using the kernel command line option memmap=nnn.
* The smallest unit the kernel accepts is in kilobytes,
--
1.8.3.1

875
SOURCES/kexec-tools-2.0.15-makedumpfile-Add-a-new-helper-file-tools.c-that-provides-some-use.patch

@ -0,0 +1,875 @@ @@ -0,0 +1,875 @@
From 4d86cc76f09f7632bb60833832406d7f294baf25 Mon Sep 17 00:00:00 2001
From: Bhupesh Sharma <bhsharma@redhat.com>
Date: Tue, 6 Mar 2018 02:13:00 +0900
Subject: [PATCH 1/3] Add a new helper file 'tools.c' that provides some useful
APIs

This patch borrows the 'tools.c' helper file from the crash utility
project and adds it to the makedumpfile source code, to allow
some basic useful APIs to be present which can be invoked from
other source code files.

'tools.c' provides some useful APIs like 'htol' (convert
a string to a hexadecimal long value), etc. which can be
invoked by other functions (a functionality that is exposed
by follow-up patches).

Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
---
Makefile | 2 +-
common.h | 8 +
makedumpfile.h | 14 ++
tools.c | 766 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 789 insertions(+), 1 deletion(-)
create mode 100644 tools.c

diff --git a/makedumpfile-1.6.2/Makefile b/makedumpfile-1.6.2/Makefile
index f4b7c56b6f3d..e870b1362c95 100644
--- a/makedumpfile-1.6.2/Makefile
+++ b/makedumpfile-1.6.2/Makefile
@@ -46,7 +46,7 @@ CFLAGS_ARCH += -m32
endif
SRC_BASE = makedumpfile.c makedumpfile.h diskdump_mod.h sadump_mod.h sadump_info.h
-SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c
+SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c tools.c
OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART))
SRC_ARCH = arch/arm.c arch/arm64.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c arch/sparc64.c
OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH))
diff --git a/makedumpfile-1.6.2/common.h b/makedumpfile-1.6.2/common.h
index 6ad3ca7b952c..6e2f657a79c7 100644
--- a/makedumpfile-1.6.2/common.h
+++ b/makedumpfile-1.6.2/common.h
@@ -19,6 +19,8 @@
#define TRUE (1)
#define FALSE (0)
#define ERROR (-1)
+#define UNUSED (-1)
+#define RETURN_ON_ERROR (0x2)
#ifndef LONG_MAX
#define LONG_MAX ((long)(~0UL>>1))
@@ -35,12 +37,18 @@
#define round(x, y) (((x) / (y)) * (y))
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
+#define NUM_HEX (0x1)
+#define NUM_DEC (0x2)
+#define NUM_EXPR (0x4)
+#define NUM_ANY (NUM_HEX|NUM_DEC|NUM_EXPR)
+
/*
* Incorrect address
*/
#define NOT_MEMMAP_ADDR (0x0)
#define NOT_KV_ADDR (0x0)
#define NOT_PADDR (ULONGLONG_MAX)
+#define BADADDR ((ulong)(-1))
#endif /* COMMON_H */
diff --git a/makedumpfile-1.6.2/makedumpfile.h b/makedumpfile-1.6.2/makedumpfile.h
index c2143a8d794b..733ac4ef40d1 100644
--- a/makedumpfile-1.6.2/makedumpfile.h
+++ b/makedumpfile-1.6.2/makedumpfile.h
@@ -244,6 +244,9 @@ isAnon(unsigned long mapping)
#define MIN_ELF_HEADER_SIZE \
MAX(MIN_ELF32_HEADER_SIZE, MIN_ELF64_HEADER_SIZE)
static inline int string_exists(char *s) { return (s ? TRUE : FALSE); }
+#define STREQ(A, B) (string_exists((char *)A) && \
+ string_exists((char *)B) && \
+ (strcmp((char *)(A), (char *)(B)) == 0))
#define STRNEQ(A, B)(string_exists((char *)(A)) && \
string_exists((char *)(B)) && \
(strncmp((char *)(A), (char *)(B), strlen((char *)(B))) == 0))
@@ -2328,4 +2331,15 @@ int prepare_splitblock_table(void);
int initialize_zlib(z_stream *stream, int level);
int finalize_zlib(z_stream *stream);
+int parse_line(char *str, char *argv[]);
+char *shift_string_left(char *s, int cnt);
+char *clean_line(char *line);
+char *strip_linefeeds(char *line);
+char *strip_beginning_whitespace(char *line);
+char *strip_ending_whitespace(char *line);
+ulong htol(char *s, int flags);
+int hexadecimal(char *s, int count);
+int decimal(char *s, int count);
+int file_exists(char *file);
+
#endif /* MAKEDUMPFILE_H */
diff --git a/makedumpfile-1.6.2/tools.c b/makedumpfile-1.6.2/tools.c
new file mode 100644
index 000000000000..5814a775d42d
--- /dev/null
+++ b/makedumpfile-1.6.2/tools.c
@@ -0,0 +1,766 @@
+/* tools.c - Borrowed from crash utility code
+ * (https://github.com/crash-utility/crash)
+ *
+ * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
+ * Copyright (C) 2002-2017 David Anderson
+ * Copyright (C) 2002-2018 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "common.h"
+#include "makedumpfile.h"
+#include <ctype.h>
+
+#define FAULT_ON_ERROR (0x1)
+#define RETURN_ON_ERROR (0x2)
+#define QUIET (0x4)
+#define HEX_BIAS (0x8)
+#define LONG_LONG (0x10)
+#define RETURN_PARTIAL (0x20)
+#define NO_DEVMEM_SWITCH (0x40)
+
+#define MAX_HEXADDR_STRLEN (16)
+
+#define FIRSTCHAR(s) (s[0])
+
+/*
+ * Determine whether a file exists, using the caller's stat structure if
+ * one was passed in.
+ */
+int
+file_exists(char *file)
+{
+ struct stat sbuf;
+
+ if (stat(file, &sbuf) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+
+/*
+ * Parse a line into tokens, populate the passed-in argv[] array, and
+ * return the count of arguments found. This function modifies the
+ * passed-string by inserting a NULL character at the end of each token.
+ * Expressions encompassed by parentheses, and strings encompassed by
+ * apostrophes, are collected into single tokens.
+ */
+int
+parse_line(char *str, char *argv[])
+{
+ int i, j, k;
+ int string;
+ int expression;
+
+ for (i = 0; i < MAXARGS; i++)
+ argv[i] = NULL;
+
+ clean_line(str);
+
+ if (str == NULL || strlen(str) == 0)
+ return(0);
+
+ i = j = k = 0;
+ string = expression = FALSE;
+
+ /*
+ * Special handling for when the first character is a '"'.
+ */
+ if (str[0] == '"') {
+next:
+ do {
+ i++;
+ } while ((str[i] != NULLCHAR) && (str[i] != '"'));
+
+ switch (str[i])
+ {
+ case NULLCHAR:
+ argv[j] = &str[k];
+ return j+1;
+ case '"':
+ argv[j++] = &str[k+1];
+ str[i++] = NULLCHAR;
+ if (str[i] == '"') {
+ k = i;
+ goto next;
+ }
+ break;
+ }
+ } else
+ argv[j++] = str;
+
+ while (TRUE) {
+ if (j == MAXARGS)
+ ERRMSG("too many arguments in string!\n");
+
+ while (str[i] != ' ' && str[i] != '\t' && str[i] != NULLCHAR) {
+ i++;
+ }
+
+ switch (str[i])
+ {
+ case ' ':
+ case '\t':
+ str[i++] = NULLCHAR;
+
+ while (str[i] == ' ' || str[i] == '\t') {
+ i++;
+ }
+
+ if (str[i] == '"') {
+ str[i] = ' ';
+ string = TRUE;
+ i++;
+ }
+
+ if (!string && str[i] == '(') {
+ expression = TRUE;
+ }
+
+ if (str[i] != NULLCHAR && str[i] != '\n') {
+ argv[j++] = &str[i];
+ if (string) {
+ string = FALSE;
+ while (str[i] != '"' && str[i] != NULLCHAR)
+ i++;
+ if (str[i] == '"')
+ str[i] = ' ';
+ }
+ if (expression) {
+ expression = FALSE;
+ while (str[i] != ')' && str[i] != NULLCHAR)
+ i++;
+ }
+ break;
+ }
+ /* else fall through */
+ case '\n':
+ str[i] = NULLCHAR;
+ /* keep falling... */
+ case NULLCHAR:
+ argv[j] = NULLCHAR;
+ return(j);
+ }
+ }
+}
+
+/*
+ * Defuse controversy re: extensions to ctype.h
+ */
+int
+whitespace(int c)
+{
+ return ((c == ' ') ||(c == '\t'));
+}
+
+int
+ascii(int c)
+{
+ return ((c >= 0) && (c <= 0x7f));
+}
+
+/*
+ * Strip line-ending whitespace and linefeeds.
+ */
+char *
+strip_line_end(char *line)
+{
+ strip_linefeeds(line);
+ strip_ending_whitespace(line);
+ return(line);
+}
+
+/*
+ * Strip line-beginning and line-ending whitespace and linefeeds.
+ */
+char *
+clean_line(char *line)
+{
+ strip_beginning_whitespace(line);
+ strip_linefeeds(line);
+ strip_ending_whitespace(line);
+ return(line);
+}
+
+/*
+ * Strip line-ending linefeeds in a string.
+ */
+char *
+strip_linefeeds(char *line)
+{
+ char *p;
+
+ if (line == NULL || strlen(line) == 0)
+ return(line);
+
+ p = &LASTCHAR(line);
+
+ while (*p == '\n') {
+ *p = NULLCHAR;
+ if (--p < line)
+ break;
+ }
+
+ return(line);
+}
+
+/*
+ * Strip a specified line-ending character in a string.
+ */
+char *
+strip_ending_char(char *line, char c)
+{
+ char *p;
+
+ if (line == NULL || strlen(line) == 0)
+ return(line);
+
+ p = &LASTCHAR(line);
+
+ if (*p == c)
+ *p = NULLCHAR;
+
+ return(line);
+}
+
+/*
+ * Strip a specified line-beginning character in a string.
+ */
+char *
+strip_beginning_char(char *line, char c)
+{
+ if (line == NULL || strlen(line) == 0)
+ return(line);
+
+ if (FIRSTCHAR(line) == c)
+ shift_string_left(line, 1);
+
+ return(line);
+}
+
+/*
+ * Strip line-ending whitespace.
+ */
+char *
+strip_ending_whitespace(char *line)
+{
+ char *p;
+
+ if (line == NULL || strlen(line) == 0)
+ return(line);
+
+ p = &LASTCHAR(line);
+
+ while (*p == ' ' || *p == '\t') {
+ *p = NULLCHAR;
+ if (p == line)
+ break;
+ p--;
+ }
+
+ return(line);
+}
+
+/*
+ * Strip line-beginning whitespace.
+ */
+char *
+strip_beginning_whitespace(char *line)
+{
+ char buf[BUFSIZE];
+ char *p;
+
+ if (line == NULL || strlen(line) == 0)
+ return(line);
+
+ strcpy(buf, line);
+ p = &buf[0];
+ while (*p == ' ' || *p == '\t')
+ p++;
+ strcpy(line, p);
+
+ return(line);
+}
+
+/*
+ * End line at first comma found.
+ */
+char *
+strip_comma(char *line)
+{
+ char *p;
+
+ if ((p = strstr(line, ",")))
+ *p = NULLCHAR;
+
+ return(line);
+}
+
+/*
+ * Strip the 0x from the beginning of a hexadecimal value string.
+ */
+char *
+strip_hex(char *line)
+{
+ if (STRNEQ(line, "0x"))
+ shift_string_left(line, 2);
+
+ return(line);
+}
+
+/*
+ * Turn a string into upper-case.
+ */
+char *
+upper_case(const char *s, char *buf)
+{
+ const char *p1;
+ char *p2;
+
+ p1 = s;
+ p2 = buf;
+
+ while (*p1) {
+ *p2 = toupper(*p1);
+ p1++, p2++;
+ }
+
+ *p2 = NULLCHAR;
+
+ return(buf);
+}
+
+/*
+ * Return pointer to first non-space/tab in a string.
+ */
+char *
+first_nonspace(char *s)
+{
+ return(s + strspn(s, " \t"));
+}
+
+/*
+ * Return pointer to first space/tab in a string. If none are found,
+ * return a pointer to the string terminating NULL.
+ */
+char *
+first_space(char *s)
+{
+ return(s + strcspn(s, " \t"));
+}
+
+/*
+ * Replace the first space/tab found in a string with a NULL character.
+ */
+char *
+null_first_space(char *s)
+{
+ char *p1;
+
+ p1 = first_space(s);
+ if (*p1)
+ *p1 = NULLCHAR;
+
+ return s;
+}
+
+/*
+ * Replace any instances of the characters in string c that are found in
+ * string s with the character passed in r.
+ */
+char *
+replace_string(char *s, char *c, char r)
+{
+ int i, j;
+
+ for (i = 0; s[i]; i++) {
+ for (j = 0; c[j]; j++) {
+ if (s[i] == c[j])
+ s[i] = r;
+ }
+ }
+
+ return s;
+}
+
+/*
+ * Find the rightmost instance of a substring in a string.
+ */
+char *
+strstr_rightmost(char *s, char *lookfor)
+{
+ char *next, *last, *p;
+
+ for (p = s, last = NULL; *p; p++) {
+ if (!(next = strstr(p, lookfor)))
+ break;
+ last = p = next;
+ }
+
+ return last;
+}
+
+/*
+ * Shifts the contents of a string to the left by cnt characters,
+ * disposing the leftmost characters.
+ */
+char *
+shift_string_left(char *s, int cnt)
+{
+ int origlen;
+
+ if (!cnt)
+ return(s);
+
+ origlen = strlen(s);
+ memmove(s, s+cnt, (origlen-cnt));
+ *(s+(origlen-cnt)) = NULLCHAR;
+ return(s);
+}
+
+/*
+ * Prints a string verbatim, allowing strings with % signs to be displayed
+ * without printf conversions.
+ */
+void
+print_verbatim(FILE *filep, char *line)
+{
+ int i;
+
+ for (i = 0; i < strlen(line); i++) {
+ fputc(line[i], filep);
+ fflush(filep);
+ }
+}
+
+char *
+fixup_percent(char *s)
+{
+ char *p1;
+
+ if ((p1 = strstr(s, "%")) == NULL)
+ return s;
+
+ s[strlen(s)+1] = NULLCHAR;
+ memmove(p1+1, p1, strlen(p1));
+ *p1 = '%';
+
+ return s;
+}
+
+/*
+ * Append a two-character string to a number to make 1, 2, 3 and 4 into
+ * 1st, 2nd, 3rd, 4th, and so on...
+ */
+char *
+ordinal(ulong val, char *buf)
+{
+ char *p1;
+
+ sprintf(buf, "%ld", val);
+ p1 = &buf[strlen(buf)-1];
+
+ switch (*p1)
+ {
+ case '1':
+ strcat(buf, "st");
+ break;
+ case '2':
+ strcat(buf, "nd");
+ break;
+ case '3':
+ strcat(buf, "rd");
+ break;
+ default:
+ strcat(buf, "th");
+ break;
+ }
+
+ return buf;
+}
+
+/*
+ * Determine whether a string contains only decimal characters.
+ * If count is non-zero, limit the search to count characters.
+ */
+int
+decimal(char *s, int count)
+{
+ char *p;
+ int cnt, digits;
+
+ if (!count) {
+ strip_line_end(s);
+ cnt = 0;
+ } else
+ cnt = count;
+
+ for (p = &s[0], digits = 0; *p; p++) {
+ switch(*p)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ digits++;
+ case ' ':
+ break;
+ default:
+ return FALSE;
+ }
+
+ if (count && (--cnt == 0))
+ break;
+ }
+
+ return (digits ? TRUE : FALSE);
+}
+
+/*
+ * Determine whether a string contains only ASCII characters.
+ */
+int
+ascii_string(char *s)
+{
+ char *p;
+
+ for (p = &s[0]; *p; p++) {
+ if (!ascii(*p))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * Check whether a string contains only printable ASCII characters.
+ */
+int
+printable_string(char *s)
+{
+ char *p;
+
+ for (p = &s[0]; *p; p++) {
+ if (!isprint(*p))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ * Convert a string to a hexadecimal long value.
+ */
+ulong
+htol(char *s, int flags)
+{
+ ulong i, j;
+ ulong n;
+
+ if (s == NULL) {
+ if (!(flags & QUIET))
+ ERRMSG("received NULL string\n");
+ goto htol_error;
+ }
+
+ if (STRNEQ(s, "0x") || STRNEQ(s, "0X"))
+ s += 2;
+
+ if (strlen(s) > MAX_HEXADDR_STRLEN) {
+ if (!(flags & QUIET))
+ ERRMSG("input string too large: \"%s\" (%d vs %d)\n",
+ s, (int)strlen(s), (int)MAX_HEXADDR_STRLEN);
+ goto htol_error;
+ }
+
+ for (n = i = 0; s[i] != 0; i++) {
+ switch (s[i])
+ {
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ j = (s[i] - 'a') + 10;
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ j = (s[i] - 'A') + 10;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '0':
+ j = s[i] - '0';
+ break;
+ case 'x':
+ case 'X':
+ case 'h':
+ continue;
+ default:
+ if (!(flags & QUIET))
+ ERRMSG("invalid input: \"%s\"\n", s);
+ goto htol_error;
+ }
+ n = (16 * n) + j;
+ }
+
+ return(n);
+
+htol_error:
+ return BADADDR;
+}
+
+/*
+ * Determine whether a string contains only hexadecimal characters.
+ * If count is non-zero, limit the search to count characters.
+ */
+int
+hexadecimal(char *s, int count)
+{
+ char *p;
+ int cnt, digits;
+
+ if (!count) {
+ strip_line_end(s);
+ cnt = 0;
+ } else
+ cnt = count;
+
+ for (p = &s[0], digits = 0; *p; p++) {
+ switch(*p)
+ {
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '0':
+ digits++;
+ case 'x':
+ case 'X':
+ break;
+
+ case ' ':
+ if (*(p+1) == NULLCHAR)
+ break;
+ else
+ return FALSE;
+ default:
+ return FALSE;
+ }
+
+ if (count && (--cnt == 0))
+ break;
+ }
+
+ return (digits ? TRUE : FALSE);
+}
+
+/*
+ * Determine whether a string contains only hexadecimal characters.
+ * and cannot be construed as a decimal number.
+ * If count is non-zero, limit the search to count characters.
+ */
+int
+hexadecimal_only(char *s, int count)
+{
+ char *p;
+ int cnt, only;
+
+ if (!count) {
+ strip_line_end(s);
+ cnt = 0;
+ } else
+ cnt = count;
+
+ only = 0;
+
+ for (p = &s[0]; *p; p++) {
+ switch(*p)
+ {
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ case 'x':
+ case 'X':
+ only++;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '0':
+ break;
+
+ case ' ':
+ if (*(p+1) == NULLCHAR)
+ break;
+ else
+ return FALSE;
+ default:
+ return FALSE;
+ }
+
+ if (count && (--cnt == 0))
+ break;
+ }
+
+ return only;
+}
--
2.7.4

39
SOURCES/kexec-tools-2.0.15-makedumpfile-Check-if-clock_gettime-requires-lrt.patch

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
From aec51ef7aee483cc5bf16844bdbacb1c70619f15 Mon Sep 17 00:00:00 2001
From: Petr Tesarik <ptesarik@suse.com>
Date: Wed, 20 Jun 2018 11:50:19 +0200
Subject: [PATCH 2/2] [PATCH 2/2] Check if clock_gettime() requires -lrt

For glibc versions before 2.17, clock_gettime() was contained in a
separate library and required linking with -lrt.

Signed-off-by: Petr Tesarik <ptesarik@suse.com>
---
Makefile | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/makedumpfile-1.6.2/Makefile b/makedumpfile-1.6.2/Makefile
index 612b9d0..142a387 100644
--- a/makedumpfile-1.6.2/Makefile
+++ b/makedumpfile-1.6.2/Makefile
@@ -68,6 +68,18 @@ endif
LIBS := -lpthread $(LIBS)
+try-run = $(shell set -e; \
+ TMP=".$$$$.tmp"; \
+ if ($(1)) >/dev/null 2>&1; \
+ then echo "$(2)"; \
+ else echo "$(3)"; \
+ fi; \
+ rm -f "$$TMP")
+
+LINK_TEST_PROG="int clock_gettime(); int main(){ return clock_gettime(); }"
+LIBS := $(LIBS) $(call try-run,\
+ echo $(LINK_TEST_PROG) | $(CC) $(CFLAGS) -o "$$TMP" -x c -,,-lrt)
+
all: makedumpfile
$(OBJ_PART): $(SRC_PART)
--
2.9.5

36
SOURCES/kexec-tools-2.0.15-makedumpfile-Documentation-Update-documentation-regarding-mem-usa.patch

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
From 8449bda73ab14516d4bf81d29503c1ea203bb865 Mon Sep 17 00:00:00 2001
From: Bhupesh Sharma <bhsharma@redhat.com>
Date: Tue, 6 Mar 2018 02:13:00 +0900
Subject: [PATCH 3/3] Documentation: Update documentation regarding
--mem-usage' option

Earlier patch in this patchset, enables the '--mem-usage' makedumpfile
option on arm64 platforms.

In addition, I have validated the '--mem-usage' makedumpfile option
on several ppc64/ppc64le and s390x machines, so update the
'makedumpfile.8' documentation to indicate that '--mem-usage' option is
supported not only on x86_64, but also on ppc64, s390x and arm64
platforms.

Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
---
makedumpfile.8 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/makedumpfile-1.6.2/makedumpfile.8 b/makedumpfile-1.6.2/makedumpfile.8
index 15db7947d62f..3ccfc65798be 100644
--- a/makedumpfile-1.6.2/makedumpfile.8
+++ b/makedumpfile-1.6.2/makedumpfile.8
@@ -593,7 +593,7 @@ last cleared on the crashed kernel, through "dmesg --clear" for example.
.TP
\fB\-\-mem-usage\fR
-This option is only for x86_64.
+This option is currently supported on x86_64, arm64, ppc64 and s390x.
This option is used to show the page numbers of current system in different
use. It should be executed in 1st kernel. By the help of this, user can know
how many pages is dumpable when different dump_level is specified. It analyzes
--
2.7.4

55
SOURCES/kexec-tools-2.0.15-makedumpfile-Fix-SECTION_MAP_MASK-for-kernel-v.13.patch

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
From a02f5f078ce635dd1633dab70869306b0a62e2e2 Mon Sep 17 00:00:00 2001
From: Pratyush Anand <panand@redhat.com>
Date: Thu, 17 Aug 2017 12:47:13 +0900
Subject: [PATCH v2] Fix SECTION_MAP_MASK for kernel >= v.13

* Required for kernel 4.13

commit 2d070eab2e82 "mm: consider zone which is not fully populated to
have holes" added a new flag SECTION_IS_ONLINE and therefore
SECTION_MAP_MASK has been changed. We are not able to find correct
mem_map in makedumpfile for kernel version v4.13-rc1 and onward because
of the above kernel change.

This patch fixes the MASK value keeping the code backward compatible

Signed-off-by: Pratyush Anand <panand@redhat.com>
---
makedumpfile.c | 5 ++++-
makedumpfile.h | 4 +++-
2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/makedumpfile-1.6.2/makedumpfile.c b/makedumpfile-1.6.2/makedumpfile.c
index 8af0c9d..5096319 100644
--- a/makedumpfile-1.6.2/makedumpfile.c
+++ b/makedumpfile-1.6.2/makedumpfile.c
@@ -3304,7 +3304,10 @@ section_mem_map_addr(unsigned long addr)
return NOT_KV_ADDR;
}
map = ULONG(mem_section + OFFSET(mem_section.section_mem_map));
- map &= SECTION_MAP_MASK;
+ if (info->kernel_version < KERNEL_VERSION(4, 13, 0))
+ map &= SECTION_MAP_MASK_4_12;
+ else
+ map &= SECTION_MAP_MASK;
free(mem_section);
return map;
diff --git a/makedumpfile-1.6.2/makedumpfile.h b/makedumpfile-1.6.2/makedumpfile.h
index b0cdd02..6f188e4 100644
--- a/makedumpfile-1.6.2/makedumpfile.h
+++ b/makedumpfile-1.6.2/makedumpfile.h
@@ -183,7 +183,9 @@ isAnon(unsigned long mapping)
#define SECTIONS_PER_ROOT() (info->sections_per_root)
#define SECTION_ROOT_MASK() (SECTIONS_PER_ROOT() - 1)
#define SECTION_NR_TO_ROOT(sec) ((sec) / SECTIONS_PER_ROOT())
-#define SECTION_MAP_LAST_BIT (1UL<<2)
+#define SECTION_IS_ONLINE (1UL<<2)
+#define SECTION_MAP_LAST_BIT (1UL<<3)
+#define SECTION_MAP_MASK_4_12 (~(SECTION_IS_ONLINE-1))
#define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1))
#define NR_SECTION_ROOTS() divideup(num_section, SECTIONS_PER_ROOT())
#define SECTION_NR_TO_PFN(sec) ((sec) << PFN_SECTION_SHIFT())
--
2.7.4

79
SOURCES/kexec-tools-2.0.15-makedumpfile-Fix-array-index-out-of-bound-exception.patch

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
From e5f96e79d69a1d295f19130da00ec6514d28a8ae Mon Sep 17 00:00:00 2001
From: Lianbo Jiang <lijiang@redhat.com>
Date: Tue, 6 Mar 2018 19:07:00 +0900
Subject: [PATCH] Fix array index out of bound exception

A data overflow may lead to a reversal, which may turn a positive
number into a large negative number, in this case, the string's
length will exceed the array size(for example, eta: -2147483648s),
here the array size is defined 16 characters. So, it is nessasary
to consider some exceptions.

Signed-off-by: Lianbo Jiang <lijiang@redhat.com>
---
print_info.c | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/makedumpfile-1.6.2/print_info.c b/makedumpfile-1.6.2/print_info.c
index e0e6a27..09e215a 100644
--- a/makedumpfile-1.6.2/print_info.c
+++ b/makedumpfile-1.6.2/print_info.c
@@ -16,6 +16,8 @@
#include "print_info.h"
#include <time.h>
#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
#define PROGRESS_MAXLEN "50"
@@ -352,18 +354,21 @@ static void calc_delta(struct timeval *tv_start, struct timeval *delta)
}
/* produce less than 12 bytes on msg */
-static int eta_to_human_short (int secs, char* msg)
+static int eta_to_human_short (int64_t secs, char* msg, int maxsize)
{
strcpy(msg, "eta: ");
msg += strlen("eta: ");
if (secs < 100)
- sprintf(msg, "%ds", secs);
+ snprintf(msg, maxsize, "%"PRId64"s", secs);
else if (secs < 100 * 60)
- sprintf(msg, "%dm%ds", secs / 60, secs % 60);
+ snprintf(msg, maxsize, "%"PRId64"m""%"PRId64"s",
+ secs / 60, secs % 60);
else if (secs < 48 * 3600)
- sprintf(msg, "%dh%dm", secs / 3600, (secs / 60) % 60);
+ snprintf(msg, maxsize, "%"PRId64"h""%"PRId64"m",
+ secs / 3600, (secs / 60) % 60);
else if (secs < 100 * 86400)
- sprintf(msg, "%dd%dh", secs / 86400, (secs / 3600) % 24);
+ snprintf(msg, maxsize, "%"PRId64"d""%"PRId64"h",
+ secs / 86400, (secs / 3600) % 24);
else
sprintf(msg, ">2day");
return 0;
@@ -379,8 +384,8 @@ print_progress(const char *msg, unsigned long current, unsigned long end, struct
static unsigned int lapse = 0;
static const char *spinner = "/|\\-";
struct timeval delta;
- double eta;
- char eta_msg[16] = " ";
+ int64_t eta;
+ char eta_msg[32] = " ";
if (current < end) {
tm = time(NULL);
@@ -395,7 +400,7 @@ print_progress(const char *msg, unsigned long current, unsigned long end, struct
calc_delta(start, &delta);
eta = delta.tv_sec + delta.tv_usec / 1e6;
eta = (100 - progress) * eta / progress;
- eta_to_human_short(eta, eta_msg);
+ eta_to_human_short(eta, eta_msg, sizeof(eta_msg));
}
if (flag_ignore_r_char) {
PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%5.1f %%] %c %16s\n",
--
2.9.5

124
SOURCES/kexec-tools-2.0.15-makedumpfile-Fix-kernel_version-variable-being-uninitia.patch

@ -0,0 +1,124 @@ @@ -0,0 +1,124 @@
From 08e08d1330f5d4dd0989bfb1558d85c82254654e Mon Sep 17 00:00:00 2001
From: Bhupesh Sharma <bhsharma@redhat.com>
Date: Fri, 17 Nov 2017 06:30:41 +0900
Subject: [PATCH 2/2] [PATCH 2/2] Fix 'kernel_version' variable being
uninitialized & introduce minor reorganization

On executing `makedumpfile --mem-usage /proc/kcore`, it
fails currently with the following error message on newer Linux kernels
like 4.13.0 or 4.14.0:

mem-usage not supported for this kernel.
You can try with -f if your kernel's kcore has valid p_paddr
makedumpfile Failed.

This happens because 'info->kernel_version' is uninitialized in function
main(). So when we perform the following check, it fails even though the
kernel version is greater than 4.11.0:

if (info->kernel_version < KERNEL_VERSION(4, 11, 0) &&
!info->flag_force) {

Fix this by reorganizing the code to:
- Add an API to populate the kernel version.
- Call this API rather than replicating the open code across other APIs
across 'makedumpfile.c'

After this patch, '--mem-usage' can be used properly with makedumpfile.
Here are the logs I observe on a Fedora 26 ppc64le system:

The kernel version is not supported.
The makedumpfile operation may be incomplete.

TYPE PAGES EXCLUDABLE DESCRIPTION
----------------------------------------------------------------------
ZERO 99 yes Pages filled with zero
NON_PRI_CACHE 7817 yes Cache pages without private flag
PRI_CACHE 63603 yes Cache pages with private flag
USER 4105 yes User process pages
FREE 165446 yes Free pages
KERN_DATA 6738 no Dumpable kernel data

page size: 65536
Total pages on system: 247808
Total size on system: 16240345088 Byte

Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
---
makedumpfile.c | 31 ++++++++++++++++++++-----------
1 file changed, 20 insertions(+), 11 deletions(-)

diff --git a/makedumpfile-1.6.2/makedumpfile.c b/makedumpfile-1.6.2/makedumpfile.c
index 7ce0c6d648aa..4bde542b4f0c 100644
--- a/makedumpfile-1.6.2/makedumpfile.c
+++ b/makedumpfile-1.6.2/makedumpfile.c
@@ -1089,6 +1089,21 @@ fallback_to_current_page_size(void)
return TRUE;
}
+static int populate_kernel_version(void)
+{
+ struct utsname utsname;
+
+ if (uname(&utsname)) {
+ ERRMSG("Cannot get name and information about current kernel : %s\n",
+ strerror(errno));
+ return FALSE;
+ }
+
+ info->kernel_version = get_kernel_version(utsname.release);
+
+ return TRUE;
+}
+
int
check_release(void)
{
@@ -1120,11 +1135,8 @@ check_release(void)
}
}
- info->kernel_version = get_kernel_version(info->system_utsname.release);
- if (info->kernel_version == FALSE) {
- ERRMSG("Can't get the kernel version.\n");
+ if (!populate_kernel_version())
return FALSE;
- }
return TRUE;
}
@@ -10973,20 +10985,14 @@ int is_crashkernel_mem_reserved(void)
static int get_page_offset(void)
{
- struct utsname utsname;
- if (uname(&utsname)) {
- ERRMSG("Cannot get name and information about current kernel : %s",
- strerror(errno));
+ if (!populate_kernel_version())
return FALSE;
- }
- info->kernel_version = get_kernel_version(utsname.release);
get_versiondep_info();
return TRUE;
}
-
/* Returns the physical address of start of crash notes buffer for a kernel. */
static int get_sys_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len)
{
@@ -11363,6 +11369,9 @@ main(int argc, char *argv[])
MSG("Try `makedumpfile --help' for more information.\n");
goto out;
}
+ if (!populate_kernel_version())
+ goto out;
+
if (info->kernel_version < KERNEL_VERSION(4, 11, 0) &&
!info->flag_force) {
MSG("mem-usage not supported for this kernel.\n");
--
2.7.4

75
SOURCES/kexec-tools-2.0.15-makedumpfile-Fix-off-by-one-errors-in-exclude_segment.patch

@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
From 590f35e773dcd51a750b9a181863660a25b66f01 Mon Sep 17 00:00:00 2001
From: Petr Tesarik <ptesarik@suse.com>
Date: Fri, 19 Jan 2018 20:46:19 +0900
Subject: [PATCH 1/2] [PATCH 1/2] Fix off-by-one errors in exclude_segment()

The crashed reserved memory end offset is the last address within
range, whereas the end offset in the pt_loads[] denotes the first
address past the range. This has caused a number of off-by-one
errors in exclude_segment().

First, let's unify the meaning of "end" to be the first out-of-range
address, i.e. start + size. Thanks to that, no +1 or -1 adjustments
are needed in exclude_segment().

Second, since the value read from /proc/iomem is the last address
within range, add one when passing it as an argument to
exclude_segment(). This is now the only adjustment by one.

Signed-off-by: Petr Tesarik <ptesarik@suse.com>
Tested-by: Bhupesh Sharma <bhsharma@redhat.com>
---
elf_info.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/makedumpfile-1.6.2/elf_info.c b/makedumpfile-1.6.2/elf_info.c
index 69b1719b020f..1eaddd968826 100644
--- a/makedumpfile-1.6.2/elf_info.c
+++ b/makedumpfile-1.6.2/elf_info.c
@@ -820,26 +820,26 @@ static int exclude_segment(struct pt_load_segment **pt_loads,
if (kvstart < vend && kvend > vstart) {
if (kvstart != vstart && kvend != vend) {
/* Split load segment */
- temp_seg.phys_start = end + 1;
+ temp_seg.phys_start = end;
temp_seg.phys_end = (*pt_loads)[i].phys_end;
- temp_seg.virt_start = kvend + 1;
+ temp_seg.virt_start = kvend;
temp_seg.virt_end = vend;
temp_seg.file_offset = (*pt_loads)[i].file_offset
+ temp_seg.virt_start - (*pt_loads)[i].virt_start;
temp_seg.file_size = temp_seg.phys_end
- temp_seg.phys_start;
- (*pt_loads)[i].virt_end = kvstart - 1;
- (*pt_loads)[i].phys_end = start - 1;
+ (*pt_loads)[i].virt_end = kvstart;
+ (*pt_loads)[i].phys_end = start;
(*pt_loads)[i].file_size -= temp_seg.file_size;
tidx = i+1;
} else if (kvstart != vstart) {
- (*pt_loads)[i].phys_end = start - 1;
- (*pt_loads)[i].virt_end = kvstart - 1;
+ (*pt_loads)[i].phys_end = start;
+ (*pt_loads)[i].virt_end = kvstart;
} else {
- (*pt_loads)[i].phys_start = end + 1;
- (*pt_loads)[i].virt_start = kvend + 1;
+ (*pt_loads)[i].phys_start = end;
+ (*pt_loads)[i].virt_start = kvend;
}
(*pt_loads)[i].file_size -= (end -start);
}
@@ -917,7 +917,7 @@ int get_kcore_dump_loads(void)
for (i = 0; i < crash_reserved_mem_nr; i++) {
exclude_segment(&pt_loads, &num_pt_loads,
- crash_reserved_mem[i].start, crash_reserved_mem[i].end);
+ crash_reserved_mem[i].start, crash_reserved_mem[i].end + 1);
}
max_file_offset = 0;
--
2.7.4

35
SOURCES/kexec-tools-2.0.15-makedumpfile-Fix-physical-to-virtual-conversion-in-excl.patch

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
From 6c1bf2a029be0615089f55d815fdb78f6e06e06a Mon Sep 17 00:00:00 2001
From: Petr Tesarik <ptesarik@suse.com>
Date: Fri, 19 Jan 2018 20:46:17 +0900
Subject: [PATCH 2/2] [PATCH 2/2] Fix physical-to-virtual conversion in
exclude_segment()

With kaslr enabled, PAGE_OFFSET may no longer be aligned to allow
calculation using bitwise OR. My fix follows the same idea as
Baoquan's commit 4c53423b995463067fbbd394e724b4d1d6ea3d62 for
set_kcore_vmcoreinfo, i.e. use arithmetic addition instead.

Signed-off-by: Petr Tesarik <ptesarik@suse.com>
Tested-by: Bhupesh Sharma <bhsharma@redhat.com>
---
elf_info.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/makedumpfile-1.6.2/elf_info.c b/makedumpfile-1.6.2/elf_info.c
index 1eaddd968826..711601a170c7 100644
--- a/makedumpfile-1.6.2/elf_info.c
+++ b/makedumpfile-1.6.2/elf_info.c
@@ -810,8 +810,8 @@ static int exclude_segment(struct pt_load_segment **pt_loads,
int i, j, tidx = -1;
unsigned long long vstart, vend, kvstart, kvend;
struct pt_load_segment temp_seg = {0};
- kvstart = (ulong)start | PAGE_OFFSET;
- kvend = (ulong)end | PAGE_OFFSET;
+ kvstart = (ulong)start + PAGE_OFFSET;
+ kvend = (ulong)end + PAGE_OFFSET;
unsigned long size;
for (i = 0; i < (*num_pt_loads); i++) {
--
2.7.4

93
SOURCES/kexec-tools-2.0.15-makedumpfile-Introduce-vtop4_x86_64_pagetable.patch

@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
From 8c89727155f4994b4e75a659e28e5eff16ff6cbc Mon Sep 17 00:00:00 2001
From: Takao Indoh <indou.takao@jp.fujitsu.com>
Date: Thu, 26 Oct 2017 20:32:54 +0900
Subject: [PATCH 2/4] [PATCH v3 2/4] Introduce vtop4_x86_64_pagetable

This patch introduces new function vtop4_x86_64_pagetable
to translate virtual address to physical address. Unlike vtop4_x86_64,
vtop4_x86_64_pagetable need a pointer of top of pagetable like CR3.

Current vtop4_x86_64 implementation uses symbol value of
init_level4_pgt, therefore vtop4_x86_64 does not work for sadump
dumpfile of kaslr enabled kernel because it does not have vmcoreinfo to
correct address of init_level4_pgt. vtop4_x86_64_pagetable requires
pagetable address instead of init_level4_pgt and sadump dumpfile can
pass CR3 value which is included in dump header.

Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
Signed-off-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
---
arch/x86_64.c | 30 +++++++++++++++++++++++-------
makedumpfile.h | 1 +
2 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/arch/x86_64.c b/arch/x86_64.c
index 08dd6b208bce..33621f1f259c 100644
--- a/makedumpfile-1.6.2/arch/x86_64.c
+++ b/makedumpfile-1.6.2/arch/x86_64.c
@@ -255,20 +255,15 @@ get_versiondep_info_x86_64(void)
* Translate a virtual address to a physical address by using 4 levels paging.
*/
unsigned long long
-vtop4_x86_64(unsigned long vaddr)
+__vtop4_x86_64(unsigned long vaddr, unsigned long pagetable)
{
unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
unsigned long pte_paddr, pte;
- if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
- ERRMSG("Can't get the symbol of init_level4_pgt.\n");
- return NOT_PADDR;
- }
-
/*
* Get PGD.
*/
- page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + info->phys_base;
+ page_dir = pagetable;
if (is_xen_memory()) {
page_dir = ptom_xen(page_dir);
if (page_dir == NOT_PADDR)
@@ -346,6 +341,27 @@ vtop4_x86_64(unsigned long vaddr)
return (pte & ENTRY_MASK) + PAGEOFFSET(vaddr);
}
+unsigned long long
+vtop4_x86_64(unsigned long vaddr)
+{
+ unsigned long pagetable;
+
+ if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
+ ERRMSG("Can't get the symbol of init_level4_pgt.\n");
+ return NOT_PADDR;
+ }
+
+ pagetable = SYMBOL(init_level4_pgt) - __START_KERNEL_map + info->phys_base;
+
+ return __vtop4_x86_64(vaddr, pagetable);
+}
+
+unsigned long long
+vtop4_x86_64_pagetable(unsigned long vaddr, unsigned long pagetable)
+{
+ return __vtop4_x86_64(vaddr, pagetable);
+}
+
/*
* for Xen extraction
*/
diff --git a/makedumpfile.h b/makedumpfile.h
index 704a6bc2f8f4..f48dc0b82d4a 100644
--- a/makedumpfile-1.6.2/makedumpfile.h
+++ b/makedumpfile-1.6.2/makedumpfile.h
@@ -978,6 +978,7 @@ int get_phys_base_x86_64(void);
int get_machdep_info_x86_64(void);
int get_versiondep_info_x86_64(void);
unsigned long long vtop4_x86_64(unsigned long vaddr);
+unsigned long long vtop4_x86_64_pagetable(unsigned long vaddr, unsigned long pagetable);
#define find_vmemmap() find_vmemmap_x86_64()
#define get_phys_base() get_phys_base_x86_64()
#define get_machdep_info() get_machdep_info_x86_64()
--
2.5.5

48
SOURCES/kexec-tools-2.0.15-makedumpfile-PATCH-Support-newer-kernels.patch

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
From 555943348e649d2c187189f7690a98555a4b3251 Mon Sep 17 00:00:00 2001
From: Atsushi Kumagai <ats-kumagai@wm.jp.nec.com>
Date: Wed, 10 Jan 2018 11:56:31 +0900
Subject: [PATCH] [PATCH] Support newer kernels.

A new makedumpfile supports newer kernels:

- 4.12, 4.13, 4.14 (x86 FLATMEM)
- 4.12, 4.13, 4.14 (x86 SPARSEMEM)
- 4.12, 4.13, 4.14 (x86_64 SPARSEMEM)

Signed-off-by: Atsushi Kumagai <ats-kumagai@wm.jp.nec.com>
Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
README | 3 +++
makedumpfile.h | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/makedumpfile-1.6.2/README b/makedumpfile-1.6.2/README
index 8de4dc6..c3eeefe 100644
--- a/makedumpfile-1.6.2/README
+++ b/makedumpfile-1.6.2/README
@@ -119,6 +119,9 @@
4.9 | OK | ** | | | | ** | | -- | OK | OK | | |
4.10 | OK | ** | | | | ** | | -- | OK | OK | | |
4.11 | OK | ** | | | | ** | | -- | OK | OK | | |
+ 4.12 | OK | ** | | | | ** | | -- | OK | OK | | |
+ 4.13 | OK | ** | | | | ** | | -- | OK | OK | | |
+ 4.14 | OK | ** | | | | ** | | -- | OK | OK | | |
OK : Support.
-- : Not support.
diff --git a/makedumpfile-1.6.2/makedumpfile.h b/makedumpfile-1.6.2/makedumpfile.h
index c1f779a..50aaffa 100644
--- a/makedumpfile-1.6.2/makedumpfile.h
+++ b/makedumpfile-1.6.2/makedumpfile.h
@@ -478,7 +478,7 @@ do { \
#define KVER_MIN_SHIFT 16
#define KERNEL_VERSION(x,y,z) (((x) << KVER_MAJ_SHIFT) | ((y) << KVER_MIN_SHIFT) | (z))
#define OLDEST_VERSION KERNEL_VERSION(2, 6, 15)/* linux-2.6.15 */
-#define LATEST_VERSION KERNEL_VERSION(4, 11, 7)/* linux-4.11.7 */
+#define LATEST_VERSION KERNEL_VERSION(4, 14, 8)/* linux-4.14.8 */
/*
* vmcoreinfo in /proc/vmcore
--
2.7.4

68
SOURCES/kexec-tools-2.0.15-makedumpfile-Support-symbol-__cpu_online_mask.patch

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
From d6d5b443c82471818d43cb87c9280a0252e763e7 Mon Sep 17 00:00:00 2001
From: Takao Indoh <indou.takao@jp.fujitsu.com>
Date: Thu, 26 Oct 2017 20:32:48 +0900
Subject: [PATCH 1/4] [PATCH v3 1/4] Support symbol __cpu_online_mask

In the upstream kernel, by commit 5aec01b83 cpu_online_mask was replaced
with macros and new variables __cpu_online_mask was added instead of it.
Sadump uses cpu_online_mask to check the cpu was online or not,
therefore it also need __cpu_online_mask symbol for this in the latest
kernel.

Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
Signed-off-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
---
makedumpfile.c | 9 +++++++--
makedumpfile.h | 1 +
sadump_info.c | 3 ++-
3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index 567ac5dc1f9e..5f2ca7d0fbc8 100644
--- a/makedumpfile-1.6.2/makedumpfile.c
+++ b/makedumpfile-1.6.2/makedumpfile.c
@@ -1519,8 +1519,13 @@ get_symbol_info(void)
SYMBOL_INIT(__per_cpu_load, "__per_cpu_load");
SYMBOL_INIT(__per_cpu_offset, "__per_cpu_offset");
SYMBOL_INIT(cpu_online_mask, "cpu_online_mask");
- if (SYMBOL(cpu_online_mask) == NOT_FOUND_SYMBOL)
- SYMBOL_INIT(cpu_online_mask, "cpu_online_map");
+ SYMBOL_INIT(__cpu_online_mask, "__cpu_online_mask");
+ if (SYMBOL(cpu_online_mask) == NOT_FOUND_SYMBOL) {
+ if (SYMBOL(__cpu_online_mask) == NOT_FOUND_SYMBOL)
+ SYMBOL_INIT(cpu_online_mask, "cpu_online_map");
+ else
+ SYMBOL_INIT(cpu_online_mask, "__cpu_online_mask");
+ }
SYMBOL_INIT(kexec_crash_image, "kexec_crash_image");
SYMBOL_INIT(node_remap_start_vaddr, "node_remap_start_vaddr");
SYMBOL_INIT(node_remap_end_vaddr, "node_remap_end_vaddr");
diff --git a/makedumpfile.h b/makedumpfile.h
index f4ba02d11f09..704a6bc2f8f4 100644
--- a/makedumpfile-1.6.2/makedumpfile.h
+++ b/makedumpfile-1.6.2/makedumpfile.h
@@ -1596,6 +1596,7 @@ struct symbol_table {
unsigned long long __per_cpu_offset;
unsigned long long __per_cpu_load;
unsigned long long cpu_online_mask;
+ unsigned long long __cpu_online_mask;
unsigned long long kexec_crash_image;
/*
diff --git a/sadump_info.c b/sadump_info.c
index 257f1be5e686..7dd22e704234 100644
--- a/makedumpfile-1.6.2/sadump_info.c
+++ b/makedumpfile-1.6.2/sadump_info.c
@@ -953,7 +953,8 @@ cpu_online_mask_init(void)
return FALSE;
}
- if (SIZE(cpumask) == NOT_FOUND_STRUCTURE)
+ if ((SIZE(cpumask) == NOT_FOUND_STRUCTURE) ||
+ (SYMBOL(__cpu_online_mask) != NOT_FOUND_SYMBOL))
cpu_online_mask_addr = SYMBOL(cpu_online_mask);
else {
--
2.5.5

139
SOURCES/kexec-tools-2.0.15-makedumpfile-Use-integer-arithmetics-for-th.patch

@ -0,0 +1,139 @@ @@ -0,0 +1,139 @@
From c6b79cbc990b3b4933730205f58812fb44b6fcd5 Mon Sep 17 00:00:00 2001
From: Petr Tesarik <ptesarik@suse.cz>
Date: Tue, 10 Apr 2018 20:39:00 +0900
Subject: [PATCH] [PATCH v2] makedumpfile: Use integer arithmetics for the
progress bar

Essentially, the estimated remaining time is calculated as:

elapsed * (100 - progress) / progress

Since the calculation is done with floating point numbers, it had
masked a division by zero (if progress is 0), producing a NaN or
infinity. The following conversion to int produces INT_MIN with GCC
on major platforms, which originally overflowed the eta buffer. This
bug was fixed by commit e5f96e79d69a1d295f19130da00ec6514d28a8ae,
but conversion of NaN and infinity is undefined behaviour in ISO C,
plus the corresponding output is still wrong, e.g.:

Copying data : [ 0.0 %] / eta:
-9223372036854775808s

Most importantly, using the FPU for a progress bar is overkill.
Since the progress percentage is reported with one decimal digit
following the decimal point, it can be stored as an integer tenths
of a percent.

Second, the estimated time can be calculated in milliseconds. Up to
49 days can be represented this way even on 32-bit platforms. Note
that delta.tv_usec can be ignored in the subtraction, because the
resulting eta is printed as seconds, so elapsed microseconds are
irrelevant.

Last but not least, the original buffer overflow was probably caused
by the wrong assumption that integers < 100 can be interpreted with
less than 3 ASCII characters, but that's not true for signed
integers. To make eta_to_human_short() a bit safer, use an unsigned
integer type.

Signed-off-by: Petr Tesarik <ptesarik@suse.com>
---
print_info.c | 43 ++++++++++++++++++++-----------------------
1 file changed, 20 insertions(+), 23 deletions(-)

diff --git a/makedumpfile-1.6.2/print_info.c b/makedumpfile-1.6.2/print_info.c
index 09e215a..6bfcd11 100644
--- a/makedumpfile-1.6.2/print_info.c
+++ b/makedumpfile-1.6.2/print_info.c
@@ -16,8 +16,6 @@
#include "print_info.h"
#include <time.h>
#include <string.h>
-#include <stdint.h>
-#include <inttypes.h>
#define PROGRESS_MAXLEN "50"
@@ -354,21 +352,18 @@ static void calc_delta(struct timeval *tv_start, struct timeval *delta)
}
/* produce less than 12 bytes on msg */
-static int eta_to_human_short (int64_t secs, char* msg, int maxsize)
+static int eta_to_human_short (unsigned long secs, char* msg)
{
strcpy(msg, "eta: ");
msg += strlen("eta: ");
if (secs < 100)
- snprintf(msg, maxsize, "%"PRId64"s", secs);
+ sprintf(msg, "%lus", secs);
else if (secs < 100 * 60)
- snprintf(msg, maxsize, "%"PRId64"m""%"PRId64"s",
- secs / 60, secs % 60);
+ sprintf(msg, "%lum%lus", secs / 60, secs % 60);
else if (secs < 48 * 3600)
- snprintf(msg, maxsize, "%"PRId64"h""%"PRId64"m",
- secs / 3600, (secs / 60) % 60);
+ sprintf(msg, "%luh%lum", secs / 3600, (secs / 60) % 60);
else if (secs < 100 * 86400)
- snprintf(msg, maxsize, "%"PRId64"d""%"PRId64"h",
- secs / 86400, (secs / 3600) % 24);
+ sprintf(msg, "%lud%luh", secs / 86400, (secs / 3600) % 24);
else
sprintf(msg, ">2day");
return 0;
@@ -378,37 +373,39 @@ static int eta_to_human_short (int64_t secs, char* msg, int maxsize)
void
print_progress(const char *msg, unsigned long current, unsigned long end, struct timeval *start)
{
- float progress;
+ unsigned progress; /* in promilles (tenths of a percent) */
time_t tm;
static time_t last_time = 0;
static unsigned int lapse = 0;
static const char *spinner = "/|\\-";
struct timeval delta;
- int64_t eta;
- char eta_msg[32] = " ";
+ unsigned long eta;
+ char eta_msg[16] = " ";
if (current < end) {
tm = time(NULL);
if (tm - last_time < 1)
return;
last_time = tm;
- progress = (float)current * 100 / end;
+ progress = current * 1000 / end;
} else
- progress = 100;
+ progress = 1000;
- if (start != NULL) {
+ if (start != NULL && progress != 0) {
calc_delta(start, &delta);
- eta = delta.tv_sec + delta.tv_usec / 1e6;
- eta = (100 - progress) * eta / progress;
- eta_to_human_short(eta, eta_msg, sizeof(eta_msg));
+ eta = 1000 * delta.tv_sec + delta.tv_usec / 1000;
+ eta = eta / progress - delta.tv_sec;
+ eta_to_human_short(eta, eta_msg);
}
if (flag_ignore_r_char) {
- PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%5.1f %%] %c %16s\n",
- msg, progress, spinner[lapse % 4], eta_msg);
+ PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3u.%u %%] %c %16s\n",
+ msg, progress / 10, progress % 10,
+ spinner[lapse % 4], eta_msg);
} else {
PROGRESS_MSG("\r");
- PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%5.1f %%] %c %16s",
- msg, progress, spinner[lapse % 4], eta_msg);
+ PROGRESS_MSG("%-" PROGRESS_MAXLEN "s: [%3u.%u %%] %c %16s",
+ msg, progress / 10, progress % 10,
+ spinner[lapse % 4], eta_msg);
}
lapse++;
}
--
2.9.5

456
SOURCES/kexec-tools-2.0.15-makedumpfile-Use-monotonic-clock-to-calculate-ETA-and-s.patch

@ -0,0 +1,456 @@ @@ -0,0 +1,456 @@
From 0f4e25c5d7c031201fa7ad384cd9562b9c9c6004 Mon Sep 17 00:00:00 2001
From: Petr Tesarik <ptesarik@suse.com>
Date: Wed, 20 Jun 2018 11:50:18 +0200
Subject: [PATCH 1/2] [PATCH 1/2] Use monotonic clock to calculate ETA and
stats

Execution time should be always measured by a monotonic clock,
because the system clock may be affected by discontinuous jumps,
e.g. when time is set manually by an admin.

Signed-off-by: Petr Tesarik <ptesarik@suse.com>
---
makedumpfile.c | 84 +++++++++++++++++++++++++++++-----------------------------
print_info.c | 30 +++++++++++----------
print_info.h | 6 ++---
3 files changed, 61 insertions(+), 59 deletions(-)

diff --git a/makedumpfile-1.6.2/makedumpfile.c b/makedumpfile-1.6.2/makedumpfile.c
index 1ed3d61..abe7a2b 100644
--- a/makedumpfile-1.6.2/makedumpfile.c
+++ b/makedumpfile-1.6.2/makedumpfile.c
@@ -5364,7 +5364,7 @@ _exclude_free_page(struct cycle *cycle)
{
int i, nr_zones, num_nodes, node;
unsigned long node_zones, zone, spanned_pages, pgdat;
- struct timeval tv_start;
+ struct timespec ts_start;
if ((node = next_online_node(0)) < 0) {
ERRMSG("Can't get next online node.\n");
@@ -5374,7 +5374,7 @@ _exclude_free_page(struct cycle *cycle)
ERRMSG("Can't get pgdat list.\n");
return FALSE;
}
- gettimeofday(&tv_start, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &ts_start);
for (num_nodes = 1; num_nodes <= vt.numnodes; num_nodes++) {
@@ -5420,7 +5420,7 @@ _exclude_free_page(struct cycle *cycle)
* print [100 %]
*/
print_progress(PROGRESS_FREE_PAGES, vt.numnodes, vt.numnodes, NULL);
- print_execution_time(PROGRESS_FREE_PAGES, &tv_start);
+ print_execution_time(PROGRESS_FREE_PAGES, &ts_start);
return TRUE;
}
@@ -5567,7 +5567,7 @@ create_1st_bitmap_file(void)
char buf[info->page_size];
mdf_pfn_t pfn, pfn_start, pfn_end, pfn_bitmap1;
unsigned long long phys_start, phys_end;
- struct timeval tv_start;
+ struct timespec ts_start;
off_t offset_page;
if (info->flag_refiltering)
@@ -5597,7 +5597,7 @@ create_1st_bitmap_file(void)
offset_page += info->page_size;
}
- gettimeofday(&tv_start, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &ts_start);
/*
* If page is on memory hole, set bit on the 1st-bitmap.
@@ -5629,7 +5629,7 @@ create_1st_bitmap_file(void)
*/
if (!info->flag_mem_usage) {
print_progress(PROGRESS_HOLES, info->max_mapnr, info->max_mapnr, NULL);
- print_execution_time(PROGRESS_HOLES, &tv_start);
+ print_execution_time(PROGRESS_HOLES, &ts_start);
}
if (!sync_1st_bitmap())
@@ -5731,7 +5731,7 @@ create_bitmap_from_memhole(struct cycle *cycle, struct dump_bitmap *bitmap, int
mdf_pfn_t pfn_start_roundup, pfn_end_round;
unsigned long pfn_start_byte, pfn_end_byte;
unsigned int num_pt_loads = get_num_pt_loads();
- struct timeval tv_start;
+ struct timespec ts_start;
/*
* At first, clear all the bits on the bitmap.
@@ -5741,7 +5741,7 @@ create_bitmap_from_memhole(struct cycle *cycle, struct dump_bitmap *bitmap, int
/*
* If page is on memory hole, set bit on the bitmap.
*/
- gettimeofday(&tv_start, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &ts_start);
for (i = 0; get_pt_load(i, &phys_start, &phys_end, NULL, NULL); i++) {
pfn_start = MAX(paddr_to_pfn(phys_start), cycle->start_pfn);
pfn_end = MIN(paddr_to_pfn(phys_end), cycle->end_pfn);
@@ -5786,7 +5786,7 @@ create_bitmap_from_memhole(struct cycle *cycle, struct dump_bitmap *bitmap, int
* print 100 %
*/
print_progress(PROGRESS_HOLES, info->max_mapnr, info->max_mapnr, NULL);
- print_execution_time(PROGRESS_HOLES, &tv_start);
+ print_execution_time(PROGRESS_HOLES, &ts_start);
return TRUE;
}
@@ -6045,14 +6045,14 @@ exclude_unnecessary_pages(struct cycle *cycle)
{
unsigned int mm;
struct mem_map_data *mmd;
- struct timeval tv_start;
+ struct timespec ts_start;
if (is_xen_memory() && !info->dom0_mapnr) {
ERRMSG("Can't get max domain-0 PFN for excluding pages.\n");
return FALSE;
}
- gettimeofday(&tv_start, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &ts_start);
for (mm = 0; mm < info->num_mem_map; mm++) {
@@ -6076,7 +6076,7 @@ exclude_unnecessary_pages(struct cycle *cycle)
*/
if (!info->flag_mem_usage) {
print_progress(PROGRESS_UNN_PAGES, info->num_mem_map, info->num_mem_map, NULL);
- print_execution_time(PROGRESS_UNN_PAGES, &tv_start);
+ print_execution_time(PROGRESS_UNN_PAGES, &ts_start);
}
return TRUE;
@@ -7474,7 +7474,7 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page)
unsigned long frac_head, frac_tail;
off_t off_seg_load, off_memory;
Elf64_Phdr load;
- struct timeval tv_start;
+ struct timespec ts_start;
struct cycle cycle = {0};
if (!info->flag_elf_dumpfile)
@@ -7499,7 +7499,7 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page)
if (!(phnum = get_phnum_memory()))
return FALSE;
- gettimeofday(&tv_start, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &ts_start);
for (i = 0; i < phnum; i++) {
if (!get_phdr_memory(i, &load))
@@ -7547,7 +7547,7 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page)
}
if ((num_dumped % per) == 0)
- print_progress(PROGRESS_COPY, num_dumped, num_dumpable, &tv_start);
+ print_progress(PROGRESS_COPY, num_dumped, num_dumpable, &ts_start);
num_dumped++;
@@ -7666,8 +7666,8 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page)
/*
* print [100 %]
*/
- print_progress(PROGRESS_COPY, num_dumpable, num_dumpable, &tv_start);
- print_execution_time(PROGRESS_COPY, &tv_start);
+ print_progress(PROGRESS_COPY, num_dumpable, num_dumpable, &ts_start);
+ print_execution_time(PROGRESS_COPY, &ts_start);
PROGRESS_MSG("\n");
return TRUE;
@@ -8008,8 +8008,8 @@ write_kdump_pages_parallel_cyclic(struct cache_data *cd_header,
mdf_pfn_t per;
mdf_pfn_t start_pfn, end_pfn;
struct page_desc pd;
- struct timeval tv_start;
- struct timeval last, new;
+ struct timespec ts_start;
+ struct timespec last, new;
pthread_t **threads = NULL;
struct thread_args *kdump_thread_args = NULL;
void *thread_result;
@@ -8047,7 +8047,7 @@ write_kdump_pages_parallel_cyclic(struct cache_data *cd_header,
per = info->num_dumpable / 10000;
per = per ? per : 1;
- gettimeofday(&tv_start, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &ts_start);
start_pfn = cycle->start_pfn;
end_pfn = cycle->end_pfn;
@@ -8095,7 +8095,7 @@ write_kdump_pages_parallel_cyclic(struct cache_data *cd_header,
* The next pfn is smallest pfn in all page_flag_buf.
*/
sem_wait(&info->page_flag_buf_sem);
- gettimeofday(&last, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &last);
while (1) {
current_pfn = end_pfn;
@@ -8138,7 +8138,7 @@ write_kdump_pages_parallel_cyclic(struct cache_data *cd_header,
* So we should recheck.
*/
if (info->page_flag_buf[consuming]->ready != FLAG_READY) {
- gettimeofday(&new, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &new);
if (new.tv_sec - last.tv_sec > WAIT_TIME) {
ERRMSG("Can't get data of pfn.\n");
goto out;
@@ -8151,7 +8151,7 @@ write_kdump_pages_parallel_cyclic(struct cache_data *cd_header,
}
if ((num_dumped % per) == 0)
- print_progress(PROGRESS_COPY, num_dumped, info->num_dumpable, &tv_start);
+ print_progress(PROGRESS_COPY, num_dumped, info->num_dumpable, &ts_start);
num_dumped++;
@@ -8187,8 +8187,8 @@ finish:
/*
* print [100 %]
*/
- print_progress(PROGRESS_COPY, num_dumped, info->num_dumpable, &tv_start);
- print_execution_time(PROGRESS_COPY, &tv_start);
+ print_progress(PROGRESS_COPY, num_dumped, info->num_dumpable, &ts_start);
+ print_execution_time(PROGRESS_COPY, &ts_start);
PROGRESS_MSG("\n");
out:
@@ -8238,7 +8238,7 @@ write_kdump_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_pag
struct page_desc pd;
unsigned char buf[info->page_size], *buf_out = NULL;
unsigned long len_buf_out;
- struct timeval tv_start;
+ struct timespec ts_start;
const off_t failed = (off_t)-1;
unsigned long len_buf_out_zlib, len_buf_out_lzo, len_buf_out_snappy;
@@ -8299,12 +8299,12 @@ write_kdump_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_pag
end_pfn = info->split_end_pfn;
}
- gettimeofday(&tv_start, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &ts_start);
for (pfn = start_pfn; pfn < end_pfn; pfn++) {
if ((num_dumped % per) == 0)
- print_progress(PROGRESS_COPY, num_dumped, info->num_dumpable, &tv_start);
+ print_progress(PROGRESS_COPY, num_dumped, info->num_dumpable, &ts_start);
/*
* Check the excluded page.
@@ -8384,8 +8384,8 @@ out:
free(wrkmem);
#endif
- print_progress(PROGRESS_COPY, num_dumped, info->num_dumpable, &tv_start);
- print_execution_time(PROGRESS_COPY, &tv_start);
+ print_progress(PROGRESS_COPY, num_dumped, info->num_dumpable, &ts_start);
+ print_execution_time(PROGRESS_COPY, &ts_start);
return ret;
}
@@ -8747,7 +8747,7 @@ write_kdump_pages_and_bitmap_cyclic(struct cache_data *cd_header, struct cache_d
off_t offset_data=0;
struct disk_dump_header *dh = info->dump_header;
unsigned char buf[info->page_size];
- struct timeval tv_start;
+ struct timespec ts_start;
cd_header->offset
= (DISKDUMP_HEADER_BLOCKS + dh->sub_hdr_size + dh->bitmap_blocks)
@@ -8829,7 +8829,7 @@ write_kdump_pages_and_bitmap_cyclic(struct cache_data *cd_header, struct cache_d
}
free_bitmap2_buffer();
- gettimeofday(&tv_start, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &ts_start);
/*
* Write the remainder.
@@ -8842,8 +8842,8 @@ write_kdump_pages_and_bitmap_cyclic(struct cache_data *cd_header, struct cache_d
/*
* print [100 %]
*/
- print_progress(PROGRESS_COPY, num_dumped, info->num_dumpable, &tv_start);
- print_execution_time(PROGRESS_COPY, &tv_start);
+ print_progress(PROGRESS_COPY, num_dumped, info->num_dumpable, &ts_start);
+ print_execution_time(PROGRESS_COPY, &ts_start);
PROGRESS_MSG("\n");
return TRUE;
@@ -9563,10 +9563,10 @@ exclude_xen4_user_domain(void)
int
exclude_xen_user_domain(void)
{
- struct timeval tv_start;
+ struct timespec ts_start;
int ret;
- gettimeofday(&tv_start, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &ts_start);
if (info->xen_crash_info.com &&
info->xen_crash_info.com->xen_major_version >= 4)
@@ -9578,7 +9578,7 @@ exclude_xen_user_domain(void)
* print [100 %]
*/
print_progress(PROGRESS_XEN_DOMAIN, 1, 1, NULL);
- print_execution_time(PROGRESS_XEN_DOMAIN, &tv_start);
+ print_execution_time(PROGRESS_XEN_DOMAIN, &ts_start);
return ret;
}
@@ -10502,7 +10502,7 @@ reassemble_kdump_pages(void)
struct disk_dump_header dh;
struct page_desc pd, pd_zero;
struct cache_data cd_pd, cd_data;
- struct timeval tv_start;
+ struct timespec ts_start;
char *data = NULL;
unsigned long data_buf_size = info->page_size;
@@ -10538,7 +10538,7 @@ reassemble_kdump_pages(void)
/*
* Write page header of zero-filled page.
*/
- gettimeofday(&tv_start, NULL);
+ clock_gettime(CLOCK_MONOTONIC, &ts_start);
if (info->dump_level & DL_EXCLUDE_ZERO) {
/*
* makedumpfile outputs the data of zero-filled page at first
@@ -10573,7 +10573,7 @@ reassemble_kdump_pages(void)
num_dumped++;
- print_progress(PROGRESS_COPY, num_dumped, num_dumpable, &tv_start);
+ print_progress(PROGRESS_COPY, num_dumped, num_dumpable, &ts_start);
if (lseek(fd, offset_ph_org, SEEK_SET) < 0) {
ERRMSG("Can't seek a file(%s). %s\n",
@@ -10670,8 +10670,8 @@ reassemble_kdump_pages(void)
size_eraseinfo))
goto out;
}
- print_progress(PROGRESS_COPY, num_dumpable, num_dumpable, &tv_start);
- print_execution_time(PROGRESS_COPY, &tv_start);
+ print_progress(PROGRESS_COPY, num_dumpable, num_dumpable, &ts_start);
+ print_execution_time(PROGRESS_COPY, &ts_start);
ret = TRUE;
out:
diff --git a/makedumpfile-1.6.2/print_info.c b/makedumpfile-1.6.2/print_info.c
index 6bfcd11..732d5b8 100644
--- a/makedumpfile-1.6.2/print_info.c
+++ b/makedumpfile-1.6.2/print_info.c
@@ -19,6 +19,8 @@
#define PROGRESS_MAXLEN "50"
+#define NSEC_PER_SEC 1000000000L
+
int message_level;
int flag_strerr_message;
int flag_ignore_r_char; /* 0: '\r' is effective. 1: not effective. */
@@ -338,16 +340,16 @@ print_usage(void)
MSG("\n");
}
-static void calc_delta(struct timeval *tv_start, struct timeval *delta)
+static void calc_delta(struct timespec *ts_start, struct timespec *delta)
{
- struct timeval tv_end;
+ struct timespec ts_end;
- gettimeofday(&tv_end, NULL);
- delta->tv_sec = tv_end.tv_sec - tv_start->tv_sec;
- delta->tv_usec = tv_end.tv_usec - tv_start->tv_usec;
- if (delta->tv_usec < 0) {
+ clock_gettime(CLOCK_MONOTONIC, &ts_end);
+ delta->tv_sec = ts_end.tv_sec - ts_start->tv_sec;
+ delta->tv_nsec = ts_end.tv_nsec - ts_start->tv_nsec;
+ if (delta->tv_nsec < 0) {
delta->tv_sec--;
- delta->tv_usec += 1000000;
+ delta->tv_nsec += NSEC_PER_SEC;
}
}
@@ -371,14 +373,14 @@ static int eta_to_human_short (unsigned long secs, char* msg)
void
-print_progress(const char *msg, unsigned long current, unsigned long end, struct timeval *start)
+print_progress(const char *msg, unsigned long current, unsigned long end, struct timespec *start)
{
unsigned progress; /* in promilles (tenths of a percent) */
time_t tm;
static time_t last_time = 0;
static unsigned int lapse = 0;
static const char *spinner = "/|\\-";
- struct timeval delta;
+ struct timespec delta;
unsigned long eta;
char eta_msg[16] = " ";
@@ -393,7 +395,7 @@ print_progress(const char *msg, unsigned long current, unsigned long end, struct
if (start != NULL && progress != 0) {
calc_delta(start, &delta);
- eta = 1000 * delta.tv_sec + delta.tv_usec / 1000;
+ eta = 1000 * delta.tv_sec + delta.tv_nsec / (NSEC_PER_SEC / 1000);
eta = eta / progress - delta.tv_sec;
eta_to_human_short(eta, eta_msg);
}
@@ -411,12 +413,12 @@ print_progress(const char *msg, unsigned long current, unsigned long end, struct
}
void
-print_execution_time(char *step_name, struct timeval *tv_start)
+print_execution_time(char *step_name, struct timespec *ts_start)
{
- struct timeval delta;
+ struct timespec delta;
- calc_delta(tv_start, &delta);
+ calc_delta(ts_start, &delta);
REPORT_MSG("STEP [%s] : %ld.%06ld seconds\n",
- step_name, delta.tv_sec, delta.tv_usec);
+ step_name, delta.tv_sec, delta.tv_nsec / 1000);
}
diff --git a/makedumpfile-1.6.2/print_info.h b/makedumpfile-1.6.2/print_info.h
index 1ce3593..49b70f4 100644
--- a/makedumpfile-1.6.2/print_info.h
+++ b/makedumpfile-1.6.2/print_info.h
@@ -17,7 +17,7 @@
#define _PRINT_INFO_H
#include <stdio.h>
-#include <sys/time.h>
+#include <time.h>
extern int message_level;
extern int flag_strerr_message;
@@ -25,9 +25,9 @@ extern int flag_ignore_r_char;
void show_version(void);
void print_usage(void);
-void print_progress(const char *msg, unsigned long current, unsigned long end, struct timeval *start);
+void print_progress(const char *msg, unsigned long current, unsigned long end, struct timespec *start);
-void print_execution_time(char *step_name, struct timeval *tv_start);
+void print_execution_time(char *step_name, struct timespec *ts_start);
/*
* Message texts
--
2.9.5

152
SOURCES/kexec-tools-2.0.15-makedumpfile-arm64-Add-support-to-read-symbols-like-_stext-from-p.patch

@ -0,0 +1,152 @@ @@ -0,0 +1,152 @@
From d1e780507b6ed4b67e5e0e4e4b7c9796dc537210 Mon Sep 17 00:00:00 2001
From: Bhupesh Sharma <bhsharma@redhat.com>
Date: Tue, 6 Mar 2018 02:13:00 +0900
Subject: [PATCH 2/3] arm64: Add support to read symbols like _stext from
'/proc/kallsyms'

On ARM64 platforms the VA_BITS supported by a linux kernel being run
can be selected by setting 'ARM64_VA_BITS_*' (see 'arch/arm64/Kconfig'
for details).

Now, to determine the 'info->page_offset' in arm64 makedumpfile
context ('arch/arm64.c') we need to determine the VA_BITS which was
selected by the underlying linux kernel.

There can be several ways to determine the VA_BITS, out of which
reading the '_stext' symbol and calculating the 'va_bits' using the
same is the simplest yet portable method.

For reading the kernel symbols like '_stext', we can read the
'/proc/kallsyms' file which contains these symbols and
works even in case of KASLR enabled arm64 kernels, as in those cases,
the '_stext' symbol will end up being randomized and hence
cannot be correctly read from the 'vmlinux' file.

Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
---
arch/arm64.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 73 insertions(+), 4 deletions(-)

diff --git a/makedumpfile-1.6.2/arch/arm64.c b/makedumpfile-1.6.2/arch/arm64.c
index 25d7a1f4db98..c9dab677f2c9 100644
--- a/makedumpfile-1.6.2/arch/arm64.c
+++ b/makedumpfile-1.6.2/arch/arm64.c
@@ -48,6 +48,12 @@ static unsigned long kimage_voffset;
#define SZ_64K (64 * 1024)
#define SZ_128M (128 * 1024 * 1024)
+#define PAGE_OFFSET_36 ((0xffffffffffffffffUL) << 36)
+#define PAGE_OFFSET_39 ((0xffffffffffffffffUL) << 39)
+#define PAGE_OFFSET_42 ((0xffffffffffffffffUL) << 42)
+#define PAGE_OFFSET_47 ((0xffffffffffffffffUL) << 47)
+#define PAGE_OFFSET_48 ((0xffffffffffffffffUL) << 48)
+
#define pgd_val(x) ((x).pgd)
#define pud_val(x) (pgd_val((x).pgd))
#define pmd_val(x) (pud_val((x).pud))
@@ -140,8 +146,6 @@ pud_offset(pgd_t *pgda, pgd_t *pgdv, unsigned long vaddr)
static int calculate_plat_config(void)
{
- va_bits = NUMBER(VA_BITS);
-
/* derive pgtable_level as per arch/arm64/Kconfig */
if ((PAGESIZE() == SZ_16K && va_bits == 36) ||
(PAGESIZE() == SZ_64K && va_bits == 42)) {
@@ -177,6 +181,44 @@ get_phys_base_arm64(void)
return TRUE;
}
+ulong
+get_stext_symbol(void)
+{
+ int found;
+ FILE *fp;
+ char buf[BUFSIZE];
+ char *kallsyms[MAXARGS];
+ ulong kallsym;
+
+ if (!file_exists("/proc/kallsyms")) {
+ ERRMSG("(%s) does not exist, will not be able to read symbols. %s\n",
+ "/proc/kallsyms", strerror(errno));
+ return FALSE;
+ }
+
+ if ((fp = fopen("/proc/kallsyms", "r")) == NULL) {
+ ERRMSG("Cannot open (%s) to read symbols. %s\n",
+ "/proc/kallsyms", strerror(errno));
+ return FALSE;
+ }
+
+ found = FALSE;
+ kallsym = 0;
+
+ while (!found && fgets(buf, BUFSIZE, fp) &&
+ (parse_line(buf, kallsyms) == 3)) {
+ if (hexadecimal(kallsyms[0], 0) &&
+ STREQ(kallsyms[2], "_stext")) {
+ kallsym = htol(kallsyms[0], 0);
+ found = TRUE;
+ break;
+ }
+ }
+ fclose(fp);
+
+ return(found ? kallsym : FALSE);
+}
+
int
get_machdep_info_arm64(void)
{
@@ -188,12 +230,10 @@ get_machdep_info_arm64(void)
kimage_voffset = NUMBER(kimage_voffset);
info->max_physmem_bits = PHYS_MASK_SHIFT;
info->section_size_bits = SECTIONS_SIZE_BITS;
- info->page_offset = 0xffffffffffffffffUL << (va_bits - 1);
DEBUG_MSG("kimage_voffset : %lx\n", kimage_voffset);
DEBUG_MSG("max_physmem_bits : %lx\n", info->max_physmem_bits);
DEBUG_MSG("section_size_bits: %lx\n", info->section_size_bits);
- DEBUG_MSG("page_offset : %lx\n", info->page_offset);
return TRUE;
}
@@ -219,6 +259,35 @@ get_xen_info_arm64(void)
int
get_versiondep_info_arm64(void)
{
+ ulong _stext;
+
+ _stext = get_stext_symbol();
+ if (!_stext) {
+ ERRMSG("Can't get the symbol of _stext.\n");
+ return FALSE;
+ }
+
+ /* Derive va_bits as per arch/arm64/Kconfig */
+ if ((_stext & PAGE_OFFSET_36) == PAGE_OFFSET_36) {
+ va_bits = 36;
+ } else if ((_stext & PAGE_OFFSET_39) == PAGE_OFFSET_39) {
+ va_bits = 39;
+ } else if ((_stext & PAGE_OFFSET_42) == PAGE_OFFSET_42) {
+ va_bits = 42;
+ } else if ((_stext & PAGE_OFFSET_47) == PAGE_OFFSET_47) {
+ va_bits = 47;
+ } else if ((_stext & PAGE_OFFSET_48) == PAGE_OFFSET_48) {
+ va_bits = 48;
+ } else {
+ ERRMSG("Cannot find a proper _stext for calculating VA_BITS\n");
+ return FALSE;
+ }
+
+ info->page_offset = (0xffffffffffffffffUL) << (va_bits - 1);
+
+ DEBUG_MSG("page_offset=%lx, va_bits=%d\n", info->page_offset,
+ va_bits);
+
return TRUE;
}
--
2.7.4

41
SOURCES/kexec-tools-2.0.15-makedumpfile-arm64-Fix-calculation-of-page_offset-in-case-we-are-.patch

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
From 441b3fd88149c03c0eb4ba373f3c6633df2f3196 Mon Sep 17 00:00:00 2001
From: Bhupesh Sharma <bhsharma@redhat.com>
Date: Fri, 29 Jun 2018 16:14:48 +0530
Subject: [PATCH] arm64: Fix calculation of page_offset in case we are running
cases other than mem-usage

Patch f49ca13e5eed5bbdc69e0fd5ef099cb46050cb3d added '--mem-usage'
support for arm64 architecture.

However, we also need to make sure that the calculation of
'page_offset' is valid in case we are running cases other than
'--mem-usage'.

This patch does the same. I tested this patch on my qualcomm and apm
mustang arm64 boards.

Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
---
arch/arm64.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/makedumpfile-1.6.2/arch/arm64.c b/makedumpfile-1.6.2/arch/arm64.c
index c9dab677f2c9..2fd3e1874376 100644
--- a/makedumpfile-1.6.2/arch/arm64.c
+++ b/makedumpfile-1.6.2/arch/arm64.c
@@ -222,6 +222,12 @@ get_stext_symbol(void)
int
get_machdep_info_arm64(void)
{
+ /* Check if va_bits is still not initialized. If still 0, call
+ * get_versiondep_info() to initialize the same.
+ */
+ if (!va_bits)
+ get_versiondep_info_arm64();
+
if (!calculate_plat_config()) {
ERRMSG("Can't determine platform config values\n");
return FALSE;
--
2.7.4

71
SOURCES/kexec-tools-2.0.15-makedumpfile-book3s-ppc64-Lower-the-max-real-address-to-53-bits.patch

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
From dc28bfc3213960b549bcc70f0d5379a6222d2c60 Mon Sep 17 00:00:00 2001
From: Bhupesh Sharma <bhsharma@redhat.com>
Date: Wed, 13 Sep 2017 05:04:00 +0900
Subject: [PATCH] [PATCH v2] book3s/ppc64: Lower the max real address to 53
bits for kernels >= v4.11

* Required for kernel 4.11

Kernel commit 2f18d533757da3899f4bedab0b2c051b080079dc lowered the
max real address on ppc64 to 53 bits.

Make similar changes in makedumpfile (on basis of the underlying kernel
version), without which the makedumpfile will fail to create a dumpfile
and instead throw a SEGV fault as shown below on kernels >= v4.11:

# makedumpfile --split -d 31 -x vmlinux vmcore dumpfile_{1,2,3} 2>&1

The kernel version is not supported.
The makedumpfile operation may be incomplete.
[ 1196.252094] makedumpfile[2367]: unhandled signal 11 at
00000100f7011ca8 nip 000000001001eecc lr 000000001001f3c0 code 30001
Segmentation fault

Signed-off-by: Bhupesh Sharma <bhsharma@redhat.com>
---
arch/ppc64.c | 8 +++++++-
makedumpfile.h | 5 +++++
2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/makedumpfile-1.6.2/arch/ppc64.c b/makedumpfile-1.6.2/arch/ppc64.c
index bacac778f73c..2f5a0daa16b2 100644
--- a/makedumpfile-1.6.2/arch/ppc64.c
+++ b/makedumpfile-1.6.2/arch/ppc64.c
@@ -307,11 +307,17 @@ ppc64_vmalloc_init(void)
}
info->pte_rpn_mask = PTE_RPN_MASK_DEFAULT;
- if (info->kernel_version >= KERNEL_VERSION(4, 6, 0)) {
+ if ((info->kernel_version >= KERNEL_VERSION(4, 6, 0)) &&
+ (info->kernel_version < KERNEL_VERSION(4, 11, 0))) {
info->pte_rpn_mask = PTE_RPN_MASK_L4_4_6;
info->pte_rpn_shift = PTE_RPN_SHIFT_L4_4_6;
}
+ if (info->kernel_version >= KERNEL_VERSION(4, 11, 0)) {
+ info->pte_rpn_mask = PTE_RPN_MASK_L4_4_11;
+ info->pte_rpn_shift = PTE_RPN_SHIFT_L4_4_11;
+ }
+
/*
* Compute ptrs per each level
*/
diff --git a/makedumpfile-1.6.2/makedumpfile.h b/makedumpfile-1.6.2/makedumpfile.h
index 7d81bbcf2234..f4ba02d11f09 100644
--- a/makedumpfile-1.6.2/makedumpfile.h
+++ b/makedumpfile-1.6.2/makedumpfile.h
@@ -692,6 +692,11 @@ unsigned long get_kvbase_arm64(void);
#define PUD_MASKED_BITS_4_7 0xc0000000000000ffUL
#define PMD_MASKED_BITS_4_7 0xc0000000000000ffUL
+#define PTE_RPN_SIZE_L4_4_11 53
+#define PTE_RPN_MASK_L4_4_11 \
+ (((1UL << PTE_RPN_SIZE_L4_4_11) - 1) & ~((1UL << info->page_shift) - 1))
+#define PTE_RPN_SHIFT_L4_4_11 info->page_shift
+
/*
* Supported MMU types
*/
--
2.7.4

92
SOURCES/kexec-tools-2.0.15-makedumpfile-fix-for-hugepages-filtering.patch

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
From 5b6fe3ecda7c000360065834e7eb14d1add8017d Mon Sep 17 00:00:00 2001
From: Hari Bathini <hbathini@linux.vnet.ibm.com>
Date: Thu, 8 Mar 2018 23:39:55 +0530
Subject: [PATCH] makedumpfile: fix for hugepages filtering

Kernel commit 036e7aa49fb2 changed 'compound_dtor' & 'compound_order'
types from 'unsigned short' to 'unsigned char'. Fix it here to ensure
hugepages are filtered properly.

Also, makedumpfile tool commit 484c6b18624 used 'int' type for 'dtor'
argument in 'isHugetlb' function. While this works in recent kernels
that use 'unsigned short/char' type for 'compound_dtor', it breaks
older kernels that used address of 'free_huge_page' as dtor. Fix it
by changing 'dtor' type.

Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
makedumpfile.c | 30 ++++++++++++++++++++++++------
makedumpfile.h | 1 +
2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/makedumpfile-1.6.2/makedumpfile.c b/makedumpfile-1.6.2/makedumpfile.c
index ed138d3..ac8483d 100644
--- a/makedumpfile-1.6.2/makedumpfile.c
+++ b/makedumpfile-1.6.2/makedumpfile.c
@@ -241,7 +241,7 @@ is_in_same_page(unsigned long vaddr1, unsigned long vaddr2)
}
static inline int
-isHugetlb(int dtor)
+isHugetlb(unsigned long dtor)
{
return ((NUMBER(HUGETLB_PAGE_DTOR) != NOT_FOUND_NUMBER)
&& (NUMBER(HUGETLB_PAGE_DTOR) == dtor))
@@ -5798,18 +5798,36 @@ __exclude_unnecessary_pages(unsigned long mem_map,
* and PGMM_CACHED is a power of 2.
*/
if ((index_pg < PGMM_CACHED - 1) && isCompoundHead(flags)) {
- if (order_offset)
- compound_order = USHORT(pcache + SIZE(page) + order_offset);
+ unsigned long long addr =
+ (unsigned long long)(pcache + SIZE(page));
+
+ if (order_offset) {
+ if (info->kernel_version >=
+ KERNEL_VERSION(4, 16, 0)) {
+ compound_order =
+ UCHAR(addr + order_offset);
+ } else {
+ compound_order =
+ USHORT(addr + order_offset);
+ }
+ }
if (dtor_offset) {
/*
* compound_dtor has been changed from the address of descriptor
* to the ID of it since linux-4.4.
*/
- if (info->kernel_version >= KERNEL_VERSION(4, 4, 0)) {
- compound_dtor = USHORT(pcache + SIZE(page) + dtor_offset);
+ if (info->kernel_version >=
+ KERNEL_VERSION(4, 16, 0)) {
+ compound_dtor =
+ UCHAR(addr + dtor_offset);
+ } else if (info->kernel_version >=
+ KERNEL_VERSION(4, 4, 0)) {
+ compound_dtor =
+ USHORT(addr + dtor_offset);
} else {
- compound_dtor = ULONG(pcache + SIZE(page) + dtor_offset);
+ compound_dtor =
+ ULONG(addr + dtor_offset);
}
}
diff --git a/makedumpfile-1.6.2/makedumpfile.h b/makedumpfile-1.6.2/makedumpfile.h
index 01eece2..4cfad98 100644
--- a/makedumpfile-1.6.2/makedumpfile.h
+++ b/makedumpfile-1.6.2/makedumpfile.h
@@ -241,6 +241,7 @@ static inline int string_exists(char *s) { return (s ? TRUE : FALSE); }
string_exists((char *)(B)) && \
(strncmp((char *)(A), (char *)(B), strlen((char *)(B))) == 0))
+#define UCHAR(ADDR) *((unsigned char *)(ADDR))
#define USHORT(ADDR) *((unsigned short *)(ADDR))
#define UINT(ADDR) *((unsigned int *)(ADDR))
#define ULONG(ADDR) *((unsigned long *)(ADDR))
--
2.7.4

169
SOURCES/kexec-tools-2.0.15-makedumpfile-ppc64-get-the-info-of-mem-reserved-for-.patch

@ -0,0 +1,169 @@ @@ -0,0 +1,169 @@
From 0300f611541ad8ec654898eebf03c8345f0263ca Mon Sep 17 00:00:00 2001
From: Pingfan Liu <piliu@redhat.com>
Date: Mon, 21 Aug 2017 12:24:14 +0900
Subject: [PATCH 2/2] [PATCH v2 2/2] ppc64: get the info of mem reserved for
crashkernel

In kernel, ppc64 does not export the mem layout by ioresource. So we
need to get the mem info for crashkernel from device tree.

Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
arch/ppc64.c | 36 ++++++++++++++++++++++++++++++++++++
makedumpfile.c | 3 +++
makedumpfile.h | 11 +++++++++++
3 files changed, 50 insertions(+)

diff --git a/makedumpfile-1.6.2/arch/ppc64.c b/makedumpfile-1.6.2/arch/ppc64.c
index 3fd6002..bacac77 100644
--- a/makedumpfile-1.6.2/arch/ppc64.c
+++ b/makedumpfile-1.6.2/arch/ppc64.c
@@ -617,4 +617,40 @@ vaddr_to_paddr_ppc64(unsigned long vaddr)
return ppc64_vtop_level4(vaddr);
}
+int arch_crashkernel_mem_size_ppc64()
+{
+ const char f_crashsize[] = "/proc/device-tree/chosen/linux,crashkernel-size";
+ const char f_crashbase[] = "/proc/device-tree/chosen/linux,crashkernel-base";
+ unsigned long crashk_sz_be, crashk_sz;
+ unsigned long crashk_base_be, crashk_base;
+ uint swap;
+ FILE *fp, *fpb;
+
+ fp = fopen(f_crashsize, "r");
+ if (!fp) {
+ ERRMSG("Cannot open %s\n", f_crashsize);
+ return FALSE;
+ }
+ fpb = fopen(f_crashbase, "r");
+ if (!fp) {
+ ERRMSG("Cannot open %s\n", f_crashbase);
+ fclose(fp);
+ return FALSE;
+ }
+
+ fread(&crashk_sz_be, sizeof(crashk_sz_be), 1, fp);
+ fread(&crashk_base_be, sizeof(crashk_base_be), 1, fpb);
+ fclose(fp);
+ fclose(fpb);
+ /* dev tree is always big endian */
+ swap = !is_bigendian();
+ crashk_sz = swap64(crashk_sz_be, swap);
+ crashk_base = swap64(crashk_base_be, swap);
+ crash_reserved_mem_nr = 1;
+ crash_reserved_mem[0].start = crashk_base;
+ crash_reserved_mem[0].end = crashk_base + crashk_sz - 1;
+
+ return TRUE;
+}
+
#endif /* powerpc64 */
diff --git a/makedumpfile-1.6.2/makedumpfile.c b/makedumpfile-1.6.2/makedumpfile.c
index 5096319..567ac5d 100644
--- a/makedumpfile-1.6.2/makedumpfile.c
+++ b/makedumpfile-1.6.2/makedumpfile.c
@@ -10945,6 +10945,9 @@ int is_crashkernel_mem_reserved(void)
{
int ret;
+ if (arch_crashkernel_mem_size())
+ return TRUE;
+
ret = iomem_for_each_line("Crash kernel\n",
crashkernel_mem_callback, NULL);
crash_reserved_mem_nr = ret;
diff --git a/makedumpfile-1.6.2/makedumpfile.h b/makedumpfile-1.6.2/makedumpfile.h
index 6f188e4..7d81bbc 100644
--- a/makedumpfile-1.6.2/makedumpfile.h
+++ b/makedumpfile-1.6.2/makedumpfile.h
@@ -936,6 +936,7 @@ int get_xen_info_arm64(void);
#define get_xen_basic_info_arch(X) get_xen_basic_info_arm64(X)
#define get_xen_info_arch(X) get_xen_info_arm64(X)
#define is_phys_addr(X) stub_true_ul(X)
+#define arch_crashkernel_mem_size() stub_false()
#endif /* aarch64 */
#ifdef __arm__
@@ -949,6 +950,7 @@ unsigned long long vaddr_to_paddr_arm(unsigned long vaddr);
#define get_kaslr_offset(X) stub_false()
#define vaddr_to_paddr(X) vaddr_to_paddr_arm(X)
#define is_phys_addr(X) stub_true_ul(X)
+#define arch_crashkernel_mem_size() stub_false()
#endif /* arm */
#ifdef __x86__
@@ -962,6 +964,7 @@ unsigned long long vaddr_to_paddr_x86(unsigned long vaddr);
#define get_kaslr_offset(X) stub_false()
#define vaddr_to_paddr(X) vaddr_to_paddr_x86(X)
#define is_phys_addr(X) stub_true_ul(X)
+#define arch_crashkernel_mem_size() stub_false()
#endif /* x86 */
#ifdef __x86_64__
@@ -977,12 +980,14 @@ unsigned long long vtop4_x86_64(unsigned long vaddr);
#define get_kaslr_offset(X) get_kaslr_offset_x86_64(X)
#define vaddr_to_paddr(X) vtop4_x86_64(X)
#define is_phys_addr(X) stub_true_ul(X)
+#define arch_crashkernel_mem_size() stub_false()
#endif /* x86_64 */
#ifdef __powerpc64__ /* powerpc64 */
int get_machdep_info_ppc64(void);
int get_versiondep_info_ppc64(void);
unsigned long long vaddr_to_paddr_ppc64(unsigned long vaddr);
+int arch_crashkernel_mem_size_ppc64(void);
#define find_vmemmap() stub_false()
#define get_phys_base() stub_true()
#define get_machdep_info() get_machdep_info_ppc64()
@@ -990,6 +995,7 @@ unsigned long long vaddr_to_paddr_ppc64(unsigned long vaddr);
#define get_kaslr_offset(X) stub_false()
#define vaddr_to_paddr(X) vaddr_to_paddr_ppc64(X)
#define is_phys_addr(X) stub_true_ul(X)
+#define arch_crashkernel_mem_size() arch_crashkernel_mem_size_ppc64()
#endif /* powerpc64 */
#ifdef __powerpc32__ /* powerpc32 */
@@ -1002,6 +1008,7 @@ unsigned long long vaddr_to_paddr_ppc(unsigned long vaddr);
#define get_kaslr_offset(X) stub_false()
#define vaddr_to_paddr(X) vaddr_to_paddr_ppc(X)
#define is_phys_addr(X) stub_true_ul(X)
+#define arch_crashkernel_mem_size() stub_false()
#endif /* powerpc32 */
#ifdef __s390x__ /* s390x */
@@ -1015,6 +1022,7 @@ int is_iomem_phys_addr_s390x(unsigned long addr);
#define get_kaslr_offset(X) stub_false()
#define vaddr_to_paddr(X) vaddr_to_paddr_s390x(X)
#define is_phys_addr(X) is_iomem_phys_addr_s390x(X)
+#define arch_crashkernel_mem_size() stub_false()
#endif /* s390x */
#ifdef __ia64__ /* ia64 */
@@ -1029,6 +1037,7 @@ unsigned long long vaddr_to_paddr_ia64(unsigned long vaddr);
#define vaddr_to_paddr(X) vaddr_to_paddr_ia64(X)
#define VADDR_REGION(X) (((unsigned long)(X)) >> REGION_SHIFT)
#define is_phys_addr(X) stub_true_ul(X)
+#define arch_crashkernel_mem_size() stub_false()
#endif /* ia64 */
#ifdef __sparc64__ /* sparc64 */
@@ -1041,6 +1050,7 @@ unsigned long long vaddr_to_paddr_sparc64(unsigned long vaddr);
#define get_versiondep_info() get_versiondep_info_sparc64()
#define vaddr_to_paddr(X) vaddr_to_paddr_sparc64(X)
#define is_phys_addr(X) stub_true_ul(X)
+#define arch_crashkernel_mem_size() stub_false()
#endif /* sparc64 */
typedef unsigned long long mdf_pfn_t;
@@ -1942,6 +1952,7 @@ int iomem_for_each_line(char *match, int (*callback)(void *data, int nr,
unsigned long base,
unsigned long length),
void *data);
+int is_bigendian(void);
/*
--
2.7.4

30
SOURCES/kexec-tools-2.0.15-makedumpfile-ppc64-set-page_offset-in-get_versiondep.patch

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
From d0f59cdf7f30e4c2e533004c32c1f1979ae86371 Mon Sep 17 00:00:00 2001
From: Pingfan Liu <piliu@redhat.com>
Date: Mon, 21 Aug 2017 12:24:13 +0900
Subject: [PATCH 1/2] [PATCH v2 1/2] ppc64: set page_offset in
get_versiondep_info_ppc64()

Envalue info->page_offset in get_versiondep_info_ppc64() is a little
misleading. But since show_mem_usage->get_page_offset->get_versiondep_info
needs to get this info, so initialize it in get_versiondep_info_ppc64().

Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
arch/ppc64.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/makedumpfile-1.6.2/arch/ppc64.c b/makedumpfile-1.6.2/arch/ppc64.c
index 6aeab7e..3fd6002 100644
--- a/makedumpfile-1.6.2/arch/ppc64.c
+++ b/makedumpfile-1.6.2/arch/ppc64.c
@@ -576,6 +576,7 @@ get_versiondep_info_ppc64()
ERRMSG("Can't initialize for vmalloc translation\n");
return FALSE;
}
+ info->page_offset = __PAGE_OFFSET;
return TRUE;
}
--
2.7.4

359
SOURCES/kexec-tools-2.0.15-makedumpfile-sadump-Fix-a-KASLR-problem-of-sadump-wh.patch

@ -0,0 +1,359 @@ @@ -0,0 +1,359 @@
From 09288f2058c8066a2729588ec668eed3e1140028 Mon Sep 17 00:00:00 2001
From: Takao Indoh <indou.takao@jp.fujitsu.com>
Date: Thu, 26 Oct 2017 20:33:01 +0900
Subject: [PATCH 4/4] [PATCH v3 4/4] sadump: Fix a KASLR problem of sadump
while kdump is working

In the calc_kaslr_offset(), kaslr_offset and phys_base are calculated
using IDTR and CR3, but this solution does not work in the following
cases.

1) If the dump is captured on early stage of kernel boot, IDTR points
early IDT table(early_idts) instead of normal IDT(idt_table).
2) If the dump is captured whle kdump is working, IDTR points IDT table
of 2nd kernel, not 1st kernel.

This patch fixes the case 2). Current implementation does not support
the case 1), need enhancement in the future. This patch gets kernel boot
parameter from "saved_command_line" and check if "elfcorehdr=" is
included in the parameter. If it's included, we are in the 2nd kernel.
Retrieve vmcoreinfo from address of "elfcorehdr=" and get kaslr_offset
and phys_base from vmcoreinfo.

Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
---
makedumpfile.c | 1 +
makedumpfile.h | 1 +
sadump_info.c | 271 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 273 insertions(+)

diff --git a/makedumpfile.c b/makedumpfile.c
index 41438a344574..6d5fc8b95415 100644
--- a/makedumpfile-1.6.2/makedumpfile.c
+++ b/makedumpfile-1.6.2/makedumpfile.c
@@ -1556,6 +1556,7 @@ get_symbol_info(void)
SYMBOL_INIT(divide_error, "divide_error");
SYMBOL_INIT(idt_table, "idt_table");
+ SYMBOL_INIT(saved_command_line, "saved_command_line");
return TRUE;
}
diff --git a/makedumpfile.h b/makedumpfile.h
index 5f814e7bc3c1..db753792bca6 100644
--- a/makedumpfile-1.6.2/makedumpfile.h
+++ b/makedumpfile-1.6.2/makedumpfile.h
@@ -1602,6 +1602,7 @@ struct symbol_table {
unsigned long long kexec_crash_image;
unsigned long long divide_error;
unsigned long long idt_table;
+ unsigned long long saved_command_line;
/*
* symbols on ppc64 arch
diff --git a/sadump_info.c b/sadump_info.c
index 29ccef881370..148d4baaa538 100644
--- a/makedumpfile-1.6.2/sadump_info.c
+++ b/makedumpfile-1.6.2/sadump_info.c
@@ -1059,6 +1059,241 @@ get_vec0_addr(ulong idtr)
}
/*
+ * Parse a string of [size[KMG]@]offset[KMG]
+ * Import from Linux kernel(lib/cmdline.c)
+ */
+static ulong memparse(char *ptr, char **retptr)
+{
+ char *endptr;
+
+ unsigned long long ret = strtoull(ptr, &endptr, 0);
+
+ switch (*endptr) {
+ case 'E':
+ case 'e':
+ ret <<= 10;
+ case 'P':
+ case 'p':
+ ret <<= 10;
+ case 'T':
+ case 't':
+ ret <<= 10;
+ case 'G':
+ case 'g':
+ ret <<= 10;
+ case 'M':
+ case 'm':
+ ret <<= 10;
+ case 'K':
+ case 'k':
+ ret <<= 10;
+ endptr++;
+ default:
+ break;
+ }
+
+ if (retptr)
+ *retptr = endptr;
+
+ return ret;
+}
+
+/*
+ * Find "elfcorehdr=" in the boot parameter of kernel and return the address
+ * of elfcorehdr.
+ */
+static ulong
+get_elfcorehdr(ulong cr3)
+{
+ char cmdline[BUFSIZE], *ptr;
+ ulong cmdline_vaddr;
+ ulong cmdline_paddr;
+ ulong buf_vaddr, buf_paddr;
+ char *end;
+ ulong elfcorehdr_addr = 0, elfcorehdr_size = 0;
+
+ if (SYMBOL(saved_command_line) == NOT_FOUND_SYMBOL) {
+ ERRMSG("Can't get the symbol of saved_command_line.\n");
+ return 0;
+ }
+ cmdline_vaddr = SYMBOL(saved_command_line);
+ if ((cmdline_paddr = vtop4_x86_64_pagetable(cmdline_vaddr, cr3)) == NOT_PADDR)
+ return 0;
+
+ DEBUG_MSG("sadump: cmdline vaddr: %lx\n", cmdline_vaddr);
+ DEBUG_MSG("sadump: cmdline paddr: %lx\n", cmdline_paddr);
+
+ if (!readmem(PADDR, cmdline_paddr, &buf_vaddr, sizeof(ulong)))
+ return 0;
+
+ if ((buf_paddr = vtop4_x86_64_pagetable(buf_vaddr, cr3)) == NOT_PADDR)
+ return 0;
+
+ DEBUG_MSG("sadump: cmdline buf vaddr: %lx\n", buf_vaddr);
+ DEBUG_MSG("sadump: cmdline buf paddr: %lx\n", buf_paddr);
+
+ memset(cmdline, 0, BUFSIZE);
+ if (!readmem(PADDR, buf_paddr, cmdline, BUFSIZE))
+ return 0;
+
+ ptr = strstr(cmdline, "elfcorehdr=");
+ if (!ptr)
+ return 0;
+
+ DEBUG_MSG("sadump: 2nd kernel detected.\n");
+
+ ptr += strlen("elfcorehdr=");
+ elfcorehdr_addr = memparse(ptr, &end);
+ if (*end == '@') {
+ elfcorehdr_size = elfcorehdr_addr;
+ elfcorehdr_addr = memparse(end + 1, &end);
+ }
+
+ DEBUG_MSG("sadump: elfcorehdr_addr: %lx\n", elfcorehdr_addr);
+ DEBUG_MSG("sadump: elfcorehdr_size: %lx\n", elfcorehdr_size);
+
+ return elfcorehdr_addr;
+}
+
+/*
+ * Get vmcoreinfo from elfcorehdr.
+ * Some codes are imported from Linux kernel(fs/proc/vmcore.c)
+ */
+static int
+get_vmcoreinfo_in_kdump_kernel(ulong elfcorehdr, ulong *addr, int *len)
+{
+ unsigned char e_ident[EI_NIDENT];
+ Elf64_Ehdr ehdr;
+ Elf64_Phdr phdr;
+ Elf64_Nhdr nhdr;
+ ulong ptr;
+ ulong nhdr_offset = 0;
+ int i;
+
+ if (!readmem(PADDR, elfcorehdr, e_ident, EI_NIDENT))
+ return FALSE;
+
+ if (e_ident[EI_CLASS] != ELFCLASS64) {
+ ERRMSG("Only ELFCLASS64 is supportd\n");
+ return FALSE;
+ }
+
+ if (!readmem(PADDR, elfcorehdr, &ehdr, sizeof(ehdr)))
+ return FALSE;
+
+ /* Sanity Check */
+ if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
+ (ehdr.e_type != ET_CORE) ||
+ ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
+ ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
+ ehdr.e_version != EV_CURRENT ||
+ ehdr.e_ehsize != sizeof(Elf64_Ehdr) ||
+ ehdr.e_phentsize != sizeof(Elf64_Phdr) ||
+ ehdr.e_phnum == 0) {
+ ERRMSG("Invalid elf header\n");
+ return FALSE;
+ }
+
+ ptr = elfcorehdr + ehdr.e_phoff;
+ for (i = 0; i < ehdr.e_phnum; i++) {
+ ulong offset;
+ char name[16];
+
+ if (!readmem(PADDR, ptr, &phdr, sizeof(phdr)))
+ return FALSE;
+
+ ptr += sizeof(phdr);
+ if (phdr.p_type != PT_NOTE)
+ continue;
+
+ offset = phdr.p_offset;
+ if (!readmem(PADDR, offset, &nhdr, sizeof(nhdr)))
+ return FALSE;
+
+ offset += divideup(sizeof(Elf64_Nhdr), sizeof(Elf64_Word))*
+ sizeof(Elf64_Word);
+ memset(name, 0, sizeof(name));
+ if (!readmem(PADDR, offset, name, sizeof(name)))
+ return FALSE;
+
+ if(!strcmp(name, "VMCOREINFO")) {
+ nhdr_offset = offset;
+ break;
+ }
+ }
+
+ if (!nhdr_offset)
+ return FALSE;
+
+ *addr = nhdr_offset +
+ divideup(nhdr.n_namesz, sizeof(Elf64_Word))*
+ sizeof(Elf64_Word);
+ *len = nhdr.n_descsz;
+
+ DEBUG_MSG("sadump: vmcoreinfo addr: %lx\n", *addr);
+ DEBUG_MSG("sadump: vmcoreinfo len: %d\n", *len);
+
+ return TRUE;
+}
+
+/*
+ * Check if current kaslr_offset/phys_base is for 1st kernel or 2nd kernel.
+ * If we are in 2nd kernel, get kaslr_offset/phys_base from vmcoreinfo.
+ *
+ * 1. Get command line and try to retrieve "elfcorehdr=" boot parameter
+ * 2. If "elfcorehdr=" is not found in command line, we are in 1st kernel.
+ * There is nothing to do.
+ * 3. If "elfcorehdr=" is found, we are in 2nd kernel. Find vmcoreinfo
+ * using "elfcorehdr=" and retrieve kaslr_offset/phys_base from vmcoreinfo.
+ */
+int
+get_kaslr_offset_from_vmcoreinfo(ulong cr3, ulong *kaslr_offset,
+ ulong *phys_base)
+{
+ ulong elfcorehdr_addr = 0;
+ ulong vmcoreinfo_addr;
+ int vmcoreinfo_len;
+ char *buf, *pos;
+ int ret = FALSE;
+
+ elfcorehdr_addr = get_elfcorehdr(cr3);
+ if (!elfcorehdr_addr)
+ return FALSE;
+
+ if (!get_vmcoreinfo_in_kdump_kernel(elfcorehdr_addr, &vmcoreinfo_addr,
+ &vmcoreinfo_len))
+ return FALSE;
+
+ if (!vmcoreinfo_len)
+ return FALSE;
+
+ DEBUG_MSG("sadump: Find vmcoreinfo in kdump memory\n");
+
+ if (!(buf = malloc(vmcoreinfo_len))) {
+ ERRMSG("Can't allocate vmcoreinfo buffer.\n");
+ return FALSE;
+ }
+
+ if (!readmem(PADDR, vmcoreinfo_addr, buf, vmcoreinfo_len))
+ goto finish;
+
+ pos = strstr(buf, STR_NUMBER("phys_base"));
+ if (!pos)
+ goto finish;
+ *phys_base = strtoull(pos + strlen(STR_NUMBER("phys_base")), NULL, 0);
+
+ pos = strstr(buf, STR_KERNELOFFSET);
+ if (!pos)
+ goto finish;
+ *kaslr_offset = strtoull(pos + strlen(STR_KERNELOFFSET), NULL, 16);
+ ret = TRUE;
+
+finish:
+ free(buf);
+ return ret;
+}
+
+/*
* Calculate kaslr_offset and phys_base
*
* kaslr_offset:
@@ -1106,6 +1341,26 @@ get_vec0_addr(ulong idtr)
*
* Note that the address (A) cannot be used instead of (E) because (A) is
* not direct map address, it's a fixed map address.
+ *
+ * This solution works in most every case, but does not work in the
+ * following case.
+ *
+ * 1) If the dump is captured on early stage of kernel boot, IDTR points
+ * early IDT table(early_idts) instead of normal IDT(idt_table).
+ * 2) If the dump is captured whle kdump is working, IDTR points
+ * IDT table of 2nd kernel, not 1st kernel.
+ *
+ * Current implementation does not support the case 1), need
+ * enhancement in the future. For the case 2), get kaslr_offset and
+ * phys_base as follows.
+ *
+ * 1) Get kaslr_offset and phys_base using the above solution.
+ * 2) Get kernel boot parameter from "saved_command_line"
+ * 3) If "elfcorehdr=" is not included in boot parameter, we are in the
+ * first kernel, nothing to do any more.
+ * 4) If "elfcorehdr=" is included in boot parameter, we are in the 2nd
+ * kernel. Retrieve vmcoreinfo from address of "elfcorehdr=" and
+ * get kaslr_offset and phys_base from vmcoreinfo.
*/
int
calc_kaslr_offset(void)
@@ -1116,6 +1371,7 @@ calc_kaslr_offset(void)
int apicid;
unsigned long divide_error_vmcore, divide_error_vmlinux;
unsigned long kaslr_offset, phys_base;
+ unsigned long kaslr_offset_kdump, phys_base_kdump;
memset(&zero, 0, sizeof(zero));
for (apicid = 0; apicid < sh->nr_cpus; ++apicid) {
@@ -1161,6 +1417,21 @@ calc_kaslr_offset(void)
if (!get_symbol_info())
return FALSE;
+ /*
+ * Check if current kaslr_offset/phys_base is for 1st kernel or 2nd
+ * kernel. If we are in 2nd kernel, get kaslr_offset/phys_base
+ * from vmcoreinfo
+ */
+ if (get_kaslr_offset_from_vmcoreinfo(cr3, &kaslr_offset_kdump,
+ &phys_base_kdump)) {
+ info->kaslr_offset = kaslr_offset_kdump;
+ info->phys_base = phys_base_kdump;
+
+ /* Reload symbol */
+ if (!get_symbol_info())
+ return FALSE;
+ }
+
DEBUG_MSG("sadump: kaslr_offset=%lx\n", info->kaslr_offset);
DEBUG_MSG("sadump: phys_base=%lx\n", info->phys_base);
--
2.5.5

262
SOURCES/kexec-tools-2.0.15-makedumpfile-sadump-Fix-a-KASLR-problem-of-sadump.patch

@ -0,0 +1,262 @@ @@ -0,0 +1,262 @@
From e1ac694b94ebfa7204c5b1fac1a87d204b48f5b4 Mon Sep 17 00:00:00 2001
From: Takao Indoh <indou.takao@jp.fujitsu.com>
Date: Thu, 26 Oct 2017 20:32:54 +0900
Subject: [PATCH 3/4] [PATCH v3 3/4] sadump: Fix a KASLR problem of sadump

This patch fix a problem that makedumpfile cannot handle a dumpfile
which is captured by sadump in KASLR enabled kernel.

When KASLR feature is enabled, a kernel is placed on the memory randomly
and therefore makedumpfile cannot handle a dumpfile captured by sadump
because addresses of kernel symbols in System.map or vmlinux are
different from actual addresses.

To solve this problem, we need to calculate kaslr offset(the difference
between original symbol address and actual address) and phys_base, and
adjust symbol table of makedumpfile. In the case of dumpfile of kdump,
these information is included in the header, but dumpfile of sadump does
not have such a information.

This patch calculate kaslr offset and phys_base to solve this problem.
Please see the comment in the calc_kaslr_offset() for the detail idea.
The basic idea is getting register (IDTR and CR3) from dump header, and
calculate kaslr_offset/phys_base using them.

Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
---
makedumpfile.c | 10 ++++
makedumpfile.h | 5 +-
sadump_info.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 155 insertions(+), 3 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index 5f2ca7d0fbc8..41438a344574 100644
--- a/makedumpfile-1.6.2/makedumpfile.c
+++ b/makedumpfile-1.6.2/makedumpfile.c
@@ -1554,6 +1554,9 @@ get_symbol_info(void)
SYMBOL_INIT(demote_segment_4k, "demote_segment_4k");
SYMBOL_INIT(cur_cpu_spec, "cur_cpu_spec");
+ SYMBOL_INIT(divide_error, "divide_error");
+ SYMBOL_INIT(idt_table, "idt_table");
+
return TRUE;
}
@@ -2249,6 +2252,13 @@ write_vmcoreinfo_data(void)
WRITE_NUMBER_UNSIGNED("kimage_voffset", kimage_voffset);
#endif
+ if (info->phys_base)
+ fprintf(info->file_vmcoreinfo, "%s%lu\n", STR_NUMBER("phys_base"),
+ info->phys_base);
+ if (info->kaslr_offset)
+ fprintf(info->file_vmcoreinfo, "%s%lx\n", STR_KERNELOFFSET,
+ info->kaslr_offset);
+
/*
* write the source file of 1st kernel
*/
diff --git a/makedumpfile.h b/makedumpfile.h
index f48dc0b82d4a..5f814e7bc3c1 100644
--- a/makedumpfile-1.6.2/makedumpfile.h
+++ b/makedumpfile-1.6.2/makedumpfile.h
@@ -45,6 +45,7 @@
#include "sadump_mod.h"
#include <pthread.h>
#include <semaphore.h>
+#include <inttypes.h>
#define VMEMMAPSTART 0xffffea0000000000UL
#define BITS_PER_WORD 64
@@ -1599,6 +1600,8 @@ struct symbol_table {
unsigned long long cpu_online_mask;
unsigned long long __cpu_online_mask;
unsigned long long kexec_crash_image;
+ unsigned long long divide_error;
+ unsigned long long idt_table;
/*
* symbols on ppc64 arch
@@ -1960,7 +1963,7 @@ int iomem_for_each_line(char *match, int (*callback)(void *data, int nr,
unsigned long length),
void *data);
int is_bigendian(void);
-
+int get_symbol_info(void);
/*
* for Xen extraction
diff --git a/sadump_info.c b/sadump_info.c
index 7dd22e704234..29ccef881370 100644
--- a/makedumpfile-1.6.2/sadump_info.c
+++ b/makedumpfile-1.6.2/sadump_info.c
@@ -1035,6 +1035,138 @@ sadump_get_max_mapnr(void)
#ifdef __x86_64__
+/*
+ * Get address of vector0 interrupt handler (Devide Error) form Interrupt
+ * Descriptor Table.
+ */
+static unsigned long
+get_vec0_addr(ulong idtr)
+{
+ struct gate_struct64 {
+ uint16_t offset_low;
+ uint16_t segment;
+ uint32_t ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
+ uint16_t offset_middle;
+ uint32_t offset_high;
+ uint32_t zero1;
+ } __attribute__((packed)) gate;
+
+ readmem(PADDR, idtr, &gate, sizeof(gate));
+
+ return ((ulong)gate.offset_high << 32)
+ + ((ulong)gate.offset_middle << 16)
+ + gate.offset_low;
+}
+
+/*
+ * Calculate kaslr_offset and phys_base
+ *
+ * kaslr_offset:
+ * The difference between original address in vmlinux and actual address
+ * placed randomly by kaslr feature. To be more accurate,
+ * kaslr_offset = actual address - original address
+ *
+ * phys_base:
+ * Physical address where the kerenel is placed. In other words, it's a
+ * physical address of __START_KERNEL_map. This is also decided randomly by
+ * kaslr.
+ *
+ * kaslr offset and phys_base are calculated as follows:
+ *
+ * kaslr_offset:
+ * 1) Get IDTR and CR3 value from the dump header.
+ * 2) Get a virtual address of IDT from IDTR value
+ * --- (A)
+ * 3) Translate (A) to physical address using CR3, which points a top of
+ * page table.
+ * --- (B)
+ * 4) Get an address of vector0 (Devide Error) interrupt handler from
+ * IDT, which are pointed by (B).
+ * --- (C)
+ * 5) Get an address of symbol "divide_error" form vmlinux
+ * --- (D)
+ *
+ * Now we have two addresses:
+ * (C)-> Actual address of "divide_error"
+ * (D)-> Original address of "divide_error" in the vmlinux
+ *
+ * kaslr_offset can be calculated by the difference between these two
+ * value.
+ *
+ * phys_base;
+ * 1) Get IDT virtual address from vmlinux
+ * --- (E)
+ *
+ * So phys_base can be calculated using relationship of directly mapped
+ * address.
+ *
+ * phys_base =
+ * Physical address(B) -
+ * (Virtual address(E) + kaslr_offset - __START_KERNEL_map)
+ *
+ * Note that the address (A) cannot be used instead of (E) because (A) is
+ * not direct map address, it's a fixed map address.
+ */
+int
+calc_kaslr_offset(void)
+{
+ struct sadump_header *sh = si->sh_memory;
+ uint64_t idtr = 0, cr3 = 0, idtr_paddr;
+ struct sadump_smram_cpu_state smram, zero;
+ int apicid;
+ unsigned long divide_error_vmcore, divide_error_vmlinux;
+ unsigned long kaslr_offset, phys_base;
+
+ memset(&zero, 0, sizeof(zero));
+ for (apicid = 0; apicid < sh->nr_cpus; ++apicid) {
+ if (!get_smram_cpu_state(apicid, &smram)) {
+ ERRMSG("get_smram_cpu_state error\n");
+ return FALSE;
+ }
+
+ if (memcmp(&smram, &zero, sizeof(smram)) != 0)
+ break;
+ }
+ if (apicid >= sh->nr_cpus) {
+ ERRMSG("Can't get smram state\n");
+ return FALSE;
+ }
+
+ idtr = ((uint64_t)smram.IdtUpper)<<32 | (uint64_t)smram.IdtLower;
+ cr3 = smram.Cr3;
+
+ /* Convert virtual address of IDT table to physical address */
+ if ((idtr_paddr = vtop4_x86_64_pagetable(idtr, cr3)) == NOT_PADDR)
+ return FALSE;
+
+ /* Now we can calculate kaslr_offset and phys_base */
+ divide_error_vmlinux = SYMBOL(divide_error);
+ divide_error_vmcore = get_vec0_addr(idtr_paddr);
+ kaslr_offset = divide_error_vmcore - divide_error_vmlinux;
+ phys_base = idtr_paddr -
+ (SYMBOL(idt_table) + kaslr_offset - __START_KERNEL_map);
+
+ info->kaslr_offset = kaslr_offset;
+ info->phys_base = phys_base;
+
+ DEBUG_MSG("sadump: idtr=%" PRIx64 "\n", idtr);
+ DEBUG_MSG("sadump: cr3=%" PRIx64 "\n", cr3);
+ DEBUG_MSG("sadump: idtr(phys)=%" PRIx64 "\n", idtr_paddr);
+ DEBUG_MSG("sadump: devide_error(vmlinux)=%lx\n",
+ divide_error_vmlinux);
+ DEBUG_MSG("sadump: devide_error(vmcore)=%lx\n",
+ divide_error_vmcore);
+
+ /* Reload symbol */
+ if (!get_symbol_info())
+ return FALSE;
+
+ DEBUG_MSG("sadump: kaslr_offset=%lx\n", info->kaslr_offset);
+ DEBUG_MSG("sadump: phys_base=%lx\n", info->phys_base);
+
+ return TRUE;
+}
+
int
sadump_virt_phys_base(void)
{
@@ -1065,6 +1197,9 @@ sadump_virt_phys_base(void)
}
failed:
+ if (calc_kaslr_offset())
+ return TRUE;
+
info->phys_base = 0;
DEBUG_MSG("sadump: failed to calculate phys_base; default to 0\n");
@@ -1518,10 +1653,14 @@ cpu_to_apicid(int cpu, int *apicid)
if (!readmem(VADDR, SYMBOL(x86_bios_cpu_apicid_early_ptr),
&early_ptr, sizeof(early_ptr)))
return FALSE;
-
+ /*
+ * Note: SYMBOL(name) value is adjusted by info->kaslr_offset,
+ * but per_cpu symbol does not need to be adjusted becasue it
+ * is not affected by kaslr.
+ */
apicid_addr = early_ptr
? SYMBOL(x86_bios_cpu_apicid_early_map)+cpu*sizeof(uint16_t)
- : per_cpu_ptr(SYMBOL(x86_bios_cpu_apicid), cpu);
+ : per_cpu_ptr(SYMBOL(x86_bios_cpu_apicid) - info->kaslr_offset, cpu);
if (!readmem(VADDR, apicid_addr, &apicid_u16, sizeof(uint16_t)))
return FALSE;
--
2.5.5

87
SOURCES/kexec-tools-2.0.15-makedumpfile-sadump-Fix-a-problem-of-PTI-enabled-kernel.patch

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
From: Takao Indoh <indou.takao@jp.fujitsu.com>
To: ats-kumagai@wm.jp.nec.com, d.hatayama@jp.fujitsu.com
Subject: [makedumpfile PATCH] sadump: Fix a problem of PTI enabled kernel
Date: Fri, 26 Jan 2018 09:22:26 +0900
Cc: kexec@lists.infradead.org
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; charset=utf-8

This patch fixes a problme that a dumpfile of sadump cannot be handled by
makedumpfile when Page Table Isolation(PTI) is enabled.

When PTI is enabled, bit 12 of CR3 register is used to split user space and
kernel space. Also bit 11:0 is used for Process Context IDentifiers(PCID). To
open a dump file of sadump, a value of CR3 is used to calculate KASLR offset and
phys_base, therefore this patch fixes to mask CR3 register value collectly for
PTI enabled kernel.

Signed-off-by: Takao Indoh <indou.takao@jp.fujitsu.com>
---
makedumpfile.c | 2 ++
makedumpfile.h | 2 ++
sadump_info.c | 9 ++++++++-
3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/makedumpfile-1.6.2/makedumpfile.c b/makedumpfile-1.6.2/makedumpfile.c
index 64b404a..247a056 100644
--- a/makedumpfile-1.6.2/makedumpfile.c
+++ b/makedumpfile-1.6.2/makedumpfile.c
@@ -1557,6 +1557,8 @@ get_symbol_info(void)
SYMBOL_INIT(divide_error, "divide_error");
SYMBOL_INIT(idt_table, "idt_table");
SYMBOL_INIT(saved_command_line, "saved_command_line");
+ SYMBOL_INIT(pti_init, "pti_init");
+ SYMBOL_INIT(kaiser_init, "kaiser_init");
return TRUE;
}
diff --git a/makedumpfile-1.6.2/makedumpfile.h b/makedumpfile-1.6.2/makedumpfile.h
index 57cf4d9..8ee4d29 100644
--- a/makedumpfile-1.6.2/makedumpfile.h
+++ b/makedumpfile-1.6.2/makedumpfile.h
@@ -1608,6 +1608,8 @@ struct symbol_table {
unsigned long long divide_error;
unsigned long long idt_table;
unsigned long long saved_command_line;
+ unsigned long long pti_init;
+ unsigned long long kaiser_init;
/*
* symbols on ppc64 arch
diff --git a/makedumpfile-1.6.2/sadump_info.c b/makedumpfile-1.6.2/sadump_info.c
index 148d4ba..dd50d48 100644
--- a/makedumpfile-1.6.2/sadump_info.c
+++ b/makedumpfile-1.6.2/sadump_info.c
@@ -1362,6 +1362,9 @@ finish:
* kernel. Retrieve vmcoreinfo from address of "elfcorehdr=" and
* get kaslr_offset and phys_base from vmcoreinfo.
*/
+#define PTI_USER_PGTABLE_BIT (info->page_shift)
+#define PTI_USER_PGTABLE_MASK (1 << PTI_USER_PGTABLE_BIT)
+#define CR3_PCID_MASK 0xFFFull
int
calc_kaslr_offset(void)
{
@@ -1389,7 +1392,11 @@ calc_kaslr_offset(void)
}
idtr = ((uint64_t)smram.IdtUpper)<<32 | (uint64_t)smram.IdtLower;
- cr3 = smram.Cr3;
+ if ((SYMBOL(pti_init) != NOT_FOUND_SYMBOL) ||
+ (SYMBOL(kaiser_init) != NOT_FOUND_SYMBOL))
+ cr3 = smram.Cr3 & ~(CR3_PCID_MASK|PTI_USER_PGTABLE_MASK);
+ else
+ cr3 = smram.Cr3 & ~CR3_PCID_MASK;
/* Convert virtual address of IDT table to physical address */
if ((idtr_paddr = vtop4_x86_64_pagetable(idtr, cr3)) == NOT_PADDR)
--
1.8.3.1



_______________________________________________
kexec mailing list
kexec@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/kexec

106
SOURCES/kexec-tools-2.0.15-makedumpfile-when-refiltering-initialize-refiltered-bitm.patch

@ -0,0 +1,106 @@ @@ -0,0 +1,106 @@
From 3adf612137e8e488fe721ba154c089efbfead30a Mon Sep 17 00:00:00 2001
From: Pingfan Liu <piliu@redhat.com>
Date: Wed, 8 Aug 2018 13:21:44 +0800
Subject: [PATCH] [PATCH v3] when refiltering, initialize refiltered bitmap2
from the kdump file's bitmap2

When refiltering on kdump format file, there is no info about pt_load[] for
exclude_nodata_pages(), and also we can not expect more data than the kdump
file can provide, hence this patch suggests to initialize the refiltered
bitmap2 from the kdump file's bitmap2. As for the statistic of pfn_memhole,
it should be calculated and discount the bits in kdump file's bitmap1.

Note about the bug reported by the following ops:
makedumpfile -l --message-level 1 -d 31 /proc/vmcore /path/to/vmcore
makedumpfile --split -d 31 ./vmcore dumpfile_{1,2,3} 2>&1
And get the following error:
Excluding unnecessary pages : [100.0 %] \
readpage_kdump_compressed: pfn(9b) is excluded from /var/crash/127.0.0.1-2018-07-02-22:10:38/vmcore.
readmem: type_addr: 1, addr:9b000, size:4096
read_pfn: Can't get the page data.
writeout_multiple_dumpfiles: Child process(2277) finished incompletely.(256)
Copying data : [ 24.6 %] - eta: 2s
makedumpfile Failed.

Cc: Kazuhito Hagio <k-hagio@ab.jp.nec.com>
Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
makedumpfile.c | 40 +++++++++++++++++++++++++++++++++++-----
1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/makedumpfile-1.6.2/makedumpfile.c b/makedumpfile-1.6.2/makedumpfile.c
index 915cbf4..3ccdaae 100644
--- a/makedumpfile-1.6.2/makedumpfile.c
+++ b/makedumpfile-1.6.2/makedumpfile.c
@@ -5516,6 +5516,27 @@ out:
"follow free lists instead of mem_map array.\n");
}
+static mdf_pfn_t count_bits(char *buf, int sz)
+{
+ char *p = buf;
+ int i, j;
+ mdf_pfn_t cnt = 0;
+
+ for (i = 0; i < sz; i++, p++) {
+ if (*p == 0)
+ continue;
+ else if (*p == 0xff) {
+ cnt += 8;
+ continue;
+ }
+ for (j = 0; j < 8; j++) {
+ if (*p & (1<<j))
+ cnt++;
+ }
+ }
+ return cnt;
+}
+
/*
* If using a dumpfile in kdump-compressed format as a source file
* instead of /proc/vmcore, 1st-bitmap of a new dumpfile must be
@@ -5549,6 +5570,7 @@ copy_1st_bitmap_from_memory(void)
info->name_memory, strerror(errno));
return FALSE;
}
+ pfn_memhole -= count_bits(buf, sizeof(buf));
if (write(info->bitmap1->fd, buf, sizeof(buf)) != sizeof(buf)) {
ERRMSG("Can't write the bitmap(%s). %s\n",
info->bitmap1->file_name, strerror(errno));
@@ -6093,19 +6115,27 @@ copy_bitmap_buffer(void)
int
copy_bitmap_file(void)
{
- off_t offset;
+ off_t base, offset = 0;
unsigned char buf[info->page_size];
const off_t failed = (off_t)-1;
+ int fd;
+ struct disk_dump_header *dh = info->dh_memory;
- offset = 0;
+ if (info->flag_refiltering) {
+ fd = info->fd_memory;
+ base = (DISKDUMP_HEADER_BLOCKS + dh->sub_hdr_size) * dh->block_size;
+ base += info->len_bitmap / 2;
+ } else {
+ fd = info->bitmap1->fd;
+ base = info->bitmap1->offset;
+ }
while (offset < (info->len_bitmap / 2)) {
- if (lseek(info->bitmap1->fd, info->bitmap1->offset + offset,
- SEEK_SET) == failed) {
+ if (lseek(fd, base + offset, SEEK_SET) == failed) {
ERRMSG("Can't seek the bitmap(%s). %s\n",
info->name_bitmap, strerror(errno));
return FALSE;
}
- if (read(info->bitmap1->fd, buf, sizeof(buf)) != sizeof(buf)) {
+ if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
ERRMSG("Can't read the dump memory(%s). %s\n",
info->name_memory, strerror(errno));
return FALSE;
--
2.7.4

48
SOURCES/kexec-tools-2.0.15-makedumpfile-x86_64-Take-care-of-init_level4_pgt-rename-.patch

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
From 64bd5db6f90ec5bb6622273fa5ee4cb80b172ade Mon Sep 17 00:00:00 2001
From: Pratyush Anand <panand@redhat.com>
Date: Fri, 4 Aug 2017 10:12:17 +0900
Subject: [PATCH] [PATCH v2] x86_64: Take care of init_level4_pgt rename in
kernel

* Required for kernel 4.13

Following commit renamed init_level4_pgt to init_top_pgt in kernel.

commit 65ade2f872b474fa8a04c2d397783350326634e6
Author: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Date: Tue Jun 6 14:31:27 2017 +0300

x86/boot/64: Rename init_level4_pgt and early_level4_pgt

This patch takes care of above kernel modification in makedumpfile.

Signed-off-by: Pratyush Anand <panand@redhat.com>
---
makedumpfile.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/makedumpfile-1.6.2/makedumpfile.c b/makedumpfile-1.6.2/makedumpfile.c
index f85003a..30230a1 100644
--- a/makedumpfile-1.6.2/makedumpfile.c
+++ b/makedumpfile-1.6.2/makedumpfile.c
@@ -1486,6 +1486,8 @@ get_symbol_info(void)
SYMBOL_INIT(_stext, "_stext");
SYMBOL_INIT(swapper_pg_dir, "swapper_pg_dir");
SYMBOL_INIT(init_level4_pgt, "init_level4_pgt");
+ if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL)
+ SYMBOL_INIT(init_level4_pgt, "init_top_pgt");
SYMBOL_INIT(vmlist, "vmlist");
SYMBOL_INIT(vmap_area_list, "vmap_area_list");
SYMBOL_INIT(node_online_map, "node_online_map");
@@ -2500,6 +2502,8 @@ read_vmcoreinfo(void)
READ_SYMBOL("_stext", _stext);
READ_SYMBOL("swapper_pg_dir", swapper_pg_dir);
READ_SYMBOL("init_level4_pgt", init_level4_pgt);
+ if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL)
+ READ_SYMBOL("init_top_pgt", init_level4_pgt);
READ_SYMBOL("vmlist", vmlist);
READ_SYMBOL("vmap_area_list", vmap_area_list);
READ_SYMBOL("node_online_map", node_online_map);
--
2.7.4

131
SOURCES/kexec-tools-2.0.15-ppc64-avoid-adding-coherent-memory-regio.patch

@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
From hbathini at linux.vnet.ibm.com Thu Aug 17 05:31:51 2017
From: hbathini at linux.vnet.ibm.com (Hari Bathini)
Date: Thu, 17 Aug 2017 18:01:51 +0530
Subject: [PATCH] kexec-tools: ppc64: avoid adding coherent memory regions to
crash memory ranges
Message-ID: <150297311110.25328.11468130779639120510.stgit@hbathini.in.ibm.com>
Content-Length: 3407
Lines: 121

Accelerator devices like GPU and FPGA cards contain onboard memory. This
onboard memory is represented as a memory only NUMA node, integrating it
with core memory subsystem. Since, the link through which these devices
are integrated to core memory goes down after a system crash and they are
meant for user workloads, avoid adding coherent device memory regions to
crash memory ranges. Without this change, makedumpfile tool tries to save
unaccessible coherent device memory regions, crashing the system.

Signed-off-by: Hari Bathini <hbathini at linux.vnet.ibm.com>
---
kexec/arch/ppc64/crashdump-ppc64.c | 64 +++++++++++++++++++++++++++++++++++-
kexec/arch/ppc64/kexec-ppc64.h | 1 +
2 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index 13995bf..7ea3983 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.c
+++ b/kexec/arch/ppc64/crashdump-ppc64.c
@@ -181,6 +181,53 @@ static int get_dyn_reconf_crash_memory_ranges(void)
return 0;
}
+/*
+ * For a given memory node, check if it is mapped to system RAM or
+ * to onboard memory on accelerator device like GPU card or such.
+ */
+static int is_coherent_device_mem(const char *fname)
+{
+ char fpath[PATH_LEN];
+ char buf[32];
+ DIR *dmem;
+ FILE *file;
+ struct dirent *mentry;
+ int cnt, ret = 0;
+
+ strcpy(fpath, fname);
+ if ((dmem = opendir(fpath)) == NULL) {
+ perror(fpath);
+ return -1;
+ }
+
+ while ((mentry = readdir(dmem)) != NULL) {
+ if (strcmp(mentry->d_name, "compatible"))
+ continue;
+
+ strcat(fpath, "/compatible");
+ if ((file = fopen(fpath, "r")) == NULL) {
+ perror(fpath);
+ ret = -1;
+ break;
+ }
+ if ((cnt = fread(buf, 1, 32, file)) < 0) {
+ perror(fpath);
+ fclose(file);
+ ret = -1;
+ break;
+ }
+ if (!strncmp(buf, "ibm,coherent-device-memory", 26)) {
+ ret = 1;
+ break;
+ }
+ fclose(file);
+ }
+
+ closedir(dmem);
+ return ret;
+}
+
+
/* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to
* create Elf headers. Keeping it separate from get_memory_ranges() as
* requirements are different in the case of normal kexec and crashdumps.
@@ -196,12 +243,12 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
{
char device_tree[256] = "/proc/device-tree/";
- char fname[256];
+ char fname[PATH_LEN];
char buf[MAXBYTES];
DIR *dir, *dmem;
FILE *file;
struct dirent *dentry, *mentry;
- int n, crash_rng_len = 0;
+ int n, ret, crash_rng_len = 0;
unsigned long long start, end;
int page_size;
@@ -240,6 +287,19 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges)
continue;
strcpy(fname, device_tree);
strcat(fname, dentry->d_name);
+
+ ret = is_coherent_device_mem(fname);
+ if (ret == -1) {
+ closedir(dir);
+ goto err;
+ } else if (ret == 1) {
+ /*
+ * Avoid adding this memory region as it is not
+ * mapped to system RAM.
+ */
+ continue;
+ }
+
if ((dmem = opendir(fname)) == NULL) {
perror(fname);
closedir(dir);
diff --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h
index 633ae77..434b4bf 100644
--- a/kexec/arch/ppc64/kexec-ppc64.h
+++ b/kexec/arch/ppc64/kexec-ppc64.h
@@ -1,6 +1,7 @@
#ifndef KEXEC_PPC64_H
#define KEXEC_PPC64_H
+#define PATH_LEN 256
#define MAXBYTES 128
#define MAX_LINE 160
#define CORE_TYPE_ELF32 1



141
SOURCES/kexec-tools-2.0.15-ppc64-fix-command-line-overflow-error.patch

@ -0,0 +1,141 @@ @@ -0,0 +1,141 @@
From 21eb397a5fc9227cd95d23e8c74a49cf6a293e57 Mon Sep 17 00:00:00 2001
From: Hari Bathini <hbathini@linux.vnet.ibm.com>
Date: Wed, 9 Aug 2017 23:47:42 +0530
Subject: [PATCH] kexec-tools: powerpc: fix command line overflow error

Since kernel commit a5980d064fe2 ("powerpc: Bump COMMAND_LINE_SIZE
to 2048"), powerpc bumped command line size to 2048 but the size
used here is still the default value of 512. Bump it to 2048 to
fix command line overflow errors observed when command line length
is above 512 bytes. Also, get rid of the multiple definitions of
COMMAND_LINE_SIZE macro in ppc architecture.

Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
kexec/arch/ppc/crashdump-powerpc.c | 6 +++++-
kexec/arch/ppc/crashdump-powerpc.h | 2 --
kexec/arch/ppc/fs2dt.c | 1 -
kexec/arch/ppc/kexec-ppc.h | 3 ++-
kexec/arch/ppc/ops.h | 1 -
kexec/arch/ppc64/crashdump-ppc64.c | 6 ++++--
kexec/arch/ppc64/crashdump-ppc64.h | 2 +-
7 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/kexec/arch/ppc/crashdump-powerpc.c b/kexec/arch/ppc/crashdump-powerpc.c
index dde6de7..4ad026f 100644
--- a/kexec/arch/ppc/crashdump-powerpc.c
+++ b/kexec/arch/ppc/crashdump-powerpc.c
@@ -252,8 +252,12 @@ static void ulltoa(unsigned long long i, char *str)
/* Append str to cmdline */
static void add_cmdline(char *cmdline, char *str)
{
+ int cmdline_size;
int cmdlen = strlen(cmdline) + strlen(str);
- if (cmdlen > (COMMAND_LINE_SIZE - 1))
+
+ cmdline_size = (kernel_version() < KERNEL_VERSION(3, 10, 0) ?
+ 512 : COMMAND_LINE_SIZE);
+ if (cmdlen > (cmdline_size - 1))
die("Command line overflow\n");
strcat(cmdline, str);
}
diff --git a/kexec/arch/ppc/crashdump-powerpc.h b/kexec/arch/ppc/crashdump-powerpc.h
index 9b9b01e..97b5095 100644
--- a/kexec/arch/ppc/crashdump-powerpc.h
+++ b/kexec/arch/ppc/crashdump-powerpc.h
@@ -20,8 +20,6 @@ extern struct arch_options_t arch_options;
#define KERNELBASE PAGE_OFFSET
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
-#define COMMAND_LINE_SIZE 512 /* from kernel */
-
#ifdef CONFIG_BOOKE
/* We don't need backup region in Book E */
#define BACKUP_SRC_START 0x0000
diff --git a/kexec/arch/ppc/fs2dt.c b/kexec/arch/ppc/fs2dt.c
index 6e77379..fed499b 100644
--- a/kexec/arch/ppc/fs2dt.c
+++ b/kexec/arch/ppc/fs2dt.c
@@ -37,7 +37,6 @@
#define TREEWORDS 65536 /* max 32 bit words for properties */
#define MEMRESERVE 256 /* max number of reserved memory blks */
#define MAX_MEMORY_RANGES 1024
-#define COMMAND_LINE_SIZE 512 /* from kernel */
static char pathname[MAXPATH];
static char propnames[NAMESPACE] = { 0 };
diff --git a/kexec/arch/ppc/kexec-ppc.h b/kexec/arch/ppc/kexec-ppc.h
index f8fd678..04e728e 100644
--- a/kexec/arch/ppc/kexec-ppc.h
+++ b/kexec/arch/ppc/kexec-ppc.h
@@ -6,6 +6,8 @@
#define CORE_TYPE_ELF32 1
#define CORE_TYPE_ELF64 2
+#define COMMAND_LINE_SIZE 2048 /* from kernel */
+
extern unsigned char setup_simple_start[];
extern uint32_t setup_simple_size;
@@ -76,7 +78,6 @@ extern int init_memory_region_info(void);
extern int read_memory_region_limits(int fd, unsigned long long *start,
unsigned long long *end);
extern int get_devtree_value(const char *fname, unsigned long long *pvalue);
-#define COMMAND_LINE_SIZE 512 /* from kernel */
/*fs2dt*/
void reserve(unsigned long long where, unsigned long long length);
diff --git a/kexec/arch/ppc/ops.h b/kexec/arch/ppc/ops.h
index 7334a05..5e7a070 100644
--- a/kexec/arch/ppc/ops.h
+++ b/kexec/arch/ppc/ops.h
@@ -12,7 +12,6 @@
#define _PPC_BOOT_OPS_H_
#include "types.h"
-#define COMMAND_LINE_SIZE 512
#define MAX_PATH_LEN 256
#define MAX_PROP_LEN 256 /* What should this be? */
diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index 5a71d51..13995bf 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.c
+++ b/kexec/arch/ppc64/crashdump-ppc64.c
@@ -381,7 +381,7 @@ static void ultoa(uint64_t i, char *str)
static int add_cmdline_param(char *cmdline, uint64_t addr, char *cmdstr,
char *byte)
{
- int cmdlen, len, align = 1024;
+ int cmdline_size, cmdlen, len, align = 1024;
char str[COMMAND_LINE_SIZE], *ptr;
/* Passing in =xxxK / =xxxM format. Saves space required in cmdline.*/
@@ -402,7 +402,9 @@ static int add_cmdline_param(char *cmdline, uint64_t addr, char *cmdstr,
strcat(str, byte);
len = strlen(str);
cmdlen = strlen(cmdline) + len;
- if (cmdlen > (COMMAND_LINE_SIZE - 1))
+ cmdline_size = (kernel_version() < KERNEL_VERSION(3, 10, 0) ?
+ 512 : COMMAND_LINE_SIZE);
+ if (cmdlen > (cmdline_size - 1))
die("Command line overflow\n");
strcat(cmdline, str);
dbgprintf("Command line after adding elfcorehdr: %s\n", cmdline);
diff --git a/kexec/arch/ppc64/crashdump-ppc64.h b/kexec/arch/ppc64/crashdump-ppc64.h
index d654c6b..42ccc31 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.h
+++ b/kexec/arch/ppc64/crashdump-ppc64.h
@@ -16,7 +16,7 @@ void add_usable_mem_rgns(unsigned long long base, unsigned long long size);
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define MAXMEM (-KERNELBASE-VMALLOCBASE)
-#define COMMAND_LINE_SIZE 512 /* from kernel */
+#define COMMAND_LINE_SIZE 2048 /* from kernel */
/* Backup Region, First 64K of System RAM. */
#define BACKUP_SRC_START 0x0000
#define BACKUP_SRC_END 0xffff
--
2.7.4

123
SOURCES/kexec-tools-2.0.15-ppc64-fix-how-RMA-top-is-deduced.patch

@ -0,0 +1,123 @@ @@ -0,0 +1,123 @@
From: Hari Bathini <hbathini@linux.vnet.ibm.com>
Date: Wed, 26 Jul 2017 22:49:41 +0530
Subject: [PATCH] kexec-tools: ppc64: fix how RMA top is deduced

Hang was observed, in purgatory, on a machine configured with
single LPAR. This was because one of the segments was loaded
outside the actual Real Memory Area (RMA) due to wrongly
deduced RMA top value.

Currently, top of real memory area, which is crucial for loading
kexec/kdump kernel, is obtained by iterating through mem nodes
and setting its value based on the base and size values of the
last mem node in the iteration. That can't always be correct as
the order of iteration may not be same and RMA base & size are
always based on the first memory property. Fix this by setting
RMA top value based on the base and size values of the memory
node that has the smallest base value (first memory property)
among all the memory nodes.

Also, correct the misnomers rmo_base and rmo_top to rma_base
and rma_top respectively.

While how RMA top is deduced was broken for sometime, the issue
may not have been seen so far, for couple of possible reasons:

1. Only one mem node was available.
2. First memory property has been the last node in
iteration when multiple mem nodes were present.

Fixes: 02f4088ffded ("kexec fix ppc64 device-tree mem node")
Reported-by: Ankit Kumar <ankit@linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Geoff Levand <geoff@infradead.org>
Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
kexec/arch/ppc64/kexec-ppc64.c | 35 +++++++++++++++++++----------------
1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
index 6e8c175..a7d708b 100644
--- a/kexec/arch/ppc64/kexec-ppc64.c
+++ b/kexec/arch/ppc64/kexec-ppc64.c
@@ -38,7 +38,7 @@
static struct memory_range *exclude_range = NULL;
static struct memory_range *memory_range = NULL;
static struct memory_range *base_memory_range = NULL;
-static uint64_t rmo_top;
+static uint64_t rma_top;
uint64_t memory_max = 0;
uint64_t memory_limit;
static int nr_memory_ranges, nr_exclude_ranges;
@@ -385,7 +385,7 @@ int get_devtree_value(const char *fname, unsigned long long *value)
*/
static int get_devtree_details(unsigned long kexec_flags)
{
- uint64_t rmo_base;
+ uint64_t rma_base = -1, base;
uint64_t tce_base;
unsigned int tce_size;
uint64_t htab_base, htab_size;
@@ -696,10 +696,13 @@ static int get_devtree_details(unsigned long kexec_flags)
perror(fname);
goto error_openfile;
}
- rmo_base = be64_to_cpu(((uint64_t *)buf)[0]);
- rmo_top = rmo_base + be64_to_cpu(((uint64_t *)buf)[1]);
- if (rmo_top > 0x30000000UL)
- rmo_top = 0x30000000UL;
+ base = be64_to_cpu(((uint64_t *)buf)[0]);
+ if (base < rma_base) {
+ rma_base = base;
+ rma_top = base + be64_to_cpu(((uint64_t *)buf)[1]);
+ if (rma_top > 0x30000000UL)
+ rma_top = 0x30000000UL;
+ }
fclose(file);
closedir(cdir);
@@ -811,14 +814,14 @@ int setup_memory_ranges(unsigned long kexec_flags)
j++;
if (j >= max_memory_ranges)
realloc_memory_ranges();
- /* Limit the end to rmo_top */
- if (memory_range[j-1].start >= rmo_top) {
+ /* Limit the end to rma_top */
+ if (memory_range[j-1].start >= rma_top) {
j--;
break;
}
- if ((memory_range[j-1].start < rmo_top) &&
- (memory_range[j-1].end >= rmo_top)) {
- memory_range[j-1].end = rmo_top;
+ if ((memory_range[j-1].start < rma_top) &&
+ (memory_range[j-1].end >= rma_top)) {
+ memory_range[j-1].end = rma_top;
break;
}
continue;
@@ -833,14 +836,14 @@ int setup_memory_ranges(unsigned long kexec_flags)
j++;
if (j >= max_memory_ranges)
realloc_memory_ranges();
- /* Limit range to rmo_top */
- if (memory_range[j-1].start >= rmo_top) {
+ /* Limit range to rma_top */
+ if (memory_range[j-1].start >= rma_top) {
j--;
break;
}
- if ((memory_range[j-1].start < rmo_top) &&
- (memory_range[j-1].end >= rmo_top)) {
- memory_range[j-1].end = rmo_top;
+ if ((memory_range[j-1].start < rma_top) &&
+ (memory_range[j-1].end >= rma_top)) {
+ memory_range[j-1].end = rma_top;
break;
}
}
--
2.7.4

28
SOURCES/kexec-tools-2.0.15-ppc64-fix-leak-while-checking-for-cohere.patch

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
From 69431282f075ab723c4886f20aa248976920aaae Mon Sep 17 00:00:00 2001
From: Hari Bathini <hbathini@linux.vnet.ibm.com>
Date: Tue, 29 Aug 2017 23:08:02 +0530
Subject: [PATCH] kexec-tools: ppc64: fix leak while checking for coherent
device memory

Signed-off-by: Hari Bathini <hbathini@linux.vnet.ibm.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Pingfan Liu <piliu@redhat.com>
---
kexec/arch/ppc64/crashdump-ppc64.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index 7ea3983..bc9f948 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.c
+++ b/kexec/arch/ppc64/crashdump-ppc64.c
@@ -217,6 +217,7 @@ static int is_coherent_device_mem(const char *fname)
break;
}
if (!strncmp(buf, "ibm,coherent-device-memory", 26)) {
+ fclose(file);
ret = 1;
break;
}
--
2.7.4

17
SOURCES/kexec-tools-2.0.3-disable-kexec-test.patch

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
diff --git kexec-tools-2.0.3/kexec_test/Makefile kexec-tools-2.0.3/kexec_test/Makefile
index fec6210..2ed4d51 100644
--- kexec-tools-2.0.3/kexec_test/Makefile
+++ kexec-tools-2.0.3/kexec_test/Makefile
@@ -8,12 +8,6 @@ dist += kexec_test/Makefile $(KEXEC_TEST_SRCS) \
kexec_test/x86-setup-legacy-pic.S
BUILD_KEXEC_TEST = no
-ifeq ($(ARCH),i386)
-BUILD_KEXEC_TEST = yes
-endif
-ifeq ($(ARCH),x86_64)
-BUILD_KEXEC_TEST = yes
-endif
ifeq ($(BUILD_KEXEC_TEST),yes)

521
SOURCES/mkdumprd

@ -0,0 +1,521 @@ @@ -0,0 +1,521 @@
#!/bin/bash --norc
# New mkdumprd
#
# Copyright 2011 Red Hat, Inc.
#
# Written by Cong Wang <amwang@redhat.com>
#

. /lib/kdump/kdump-lib.sh
export IN_KDUMP=1

conf_file="/etc/kdump.conf"
SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa"
SAVE_PATH=$(grep ^path $conf_file| cut -d' ' -f2)
[ -z "$SAVE_PATH" ] && SAVE_PATH=$DEFAULT_PATH
# strip the duplicated "/"
SAVE_PATH=$(echo $SAVE_PATH | tr -s /)

is_wdt_addition_needed() {
local active

is_wdt_mod_omitted
[[ $? -eq 0 ]] && return 1
[[ -d /sys/class/watchdog/ ]] || return 1
for dir in /sys/class/watchdog/*; do
[[ -f "$dir/state" ]] || continue
active=$(< "$dir/state")
[[ "$active" = "active" ]] && return 0
done
return 1
}

WDTCFG=""
is_wdt_addition_needed
[[ $? -eq 0 ]] && WDTCFG="-a watchdog"

extra_modules=""
dracut_args=("--hostonly" "--hostonly-cmdline" "--hostonly-i18n" "--hostonly-mode" "strict" "-o" "plymouth dash resume ifcfg" $WDTCFG)
OVERRIDE_RESETTABLE=0

add_dracut_arg() {
local arg qarg is_quoted=0
while [ $# -gt 0 ];
do
arg="${1//\'/\"}"
#Handle quoted substring properly for passing it to dracut_args array.
if [ $is_quoted -eq 0 ]; then
if [[ "$arg" == "\"" ]] || [[ $arg != ${arg#\"} ]]; then
is_quoted=1
arg=${arg#\"}
fi
fi
if [ $is_quoted -eq 1 ]; then
qarg="$qarg $arg"
if [[ "$arg" == "\"" ]] || [[ $arg != ${arg%\"} ]]; then
is_quoted=0
arg=${qarg%\"}
qarg=""
else
shift
continue
fi
fi
dracut_args+=("$arg")
shift
done
}

add_dracut_module() {
add_dracut_arg "--add" "$1"
}

add_dracut_mount() {
add_dracut_arg "--mount" "$1"
}

add_dracut_sshkey() {
add_dracut_arg "--sshkey" "$1"
}

# Generic substring function. If $2 is in $1, return 0.
strstr() { [[ $1 =~ $2 ]]; }

# caller should ensure $1 is valid and mounted in 1st kernel
to_mount() {
local _dev=$1 _source _target _fstype _options _mntopts _pdev

_source=$(findmnt -k -f -n -r -o SOURCE $_dev)
_target=$(get_mntpoint_from_target $_dev)
# mount under /sysroot if dump to root disk or mount under
#/kdumproot/$_target in other cases in 2nd kernel. systemd
#will be in charge to umount it.

if [ "$_target" = "/" ];then
_target="/sysroot"
else
_target="/kdumproot/$_target"
fi

_fstype=$(findmnt -k -f -n -r -o FSTYPE $_dev)
[[ -e /etc/fstab ]] && _options=$(findmnt --fstab -f -n -r -o OPTIONS $_dev)
[ -z "$_options" ] && _options=$(findmnt -k -f -n -r -o OPTIONS $_dev)
# with 'noauto' in fstab nfs and non-root disk mount will fail in 2nd
# kernel, filter it out here.
_options=$(echo $_options | sed 's/\bnoauto\b//')
#mount fs target as rw in 2nd kernel
_options=$(echo $_options | sed 's/\bro\b/rw/')

_mntopts="$_target $_fstype $_options"
#for non-nfs _dev converting to use udev persistent name
if [ -b "$_source" ]; then
_pdev="$(kdump_get_persistent_dev $_source $_fstype)"
if [ $? -ne 0 ]; then
return 1
fi

else
_pdev=$_dev
fi

echo "$_pdev $_mntopts"
}

is_readonly_mount() {
local _mnt
_mnt=$(findmnt -k -f -n -r -o OPTIONS $1)

#fs/proc_namespace.c: show_mountinfo():
#seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw");
[[ "$_mnt" =~ ^ro ]]
}

#Function: get_ssh_size
#$1=dump target
#called from while loop and shouldn't read from stdin, so we're using "ssh -n"
get_ssh_size() {
local _opt _out _size
_opt="-i $SSH_KEY_LOCATION -o BatchMode=yes -o StrictHostKeyChecking=yes"
_out=$(ssh -q -n $_opt $1 "df -P $SAVE_PATH")
[ $? -ne 0 ] && {
perror_exit "checking remote ssh server available size failed."
}

#ssh output removed the line break, so print field NF-2
_size=$(echo -n $_out| awk '{avail=NF-2; print $avail}')
echo -n $_size
}

#mkdir if save path does not exist on ssh dump target
#$1=ssh dump target
#caller should ensure write permission on $DUMP_TARGET:$SAVE_PATH
#called from while loop and shouldn't read from stdin, so we're using "ssh -n"
mkdir_save_path_ssh()
{
local _opt _dir
_opt="-i $SSH_KEY_LOCATION -o BatchMode=yes -o StrictHostKeyChecking=yes"
ssh -qn $_opt $1 mkdir -p $SAVE_PATH 2>&1 > /dev/null
_ret=$?
if [ $_ret -ne 0 ]; then
perror_exit "mkdir failed on $DUMP_TARGET:$SAVE_PATH"
fi

#check whether user has write permission on $SAVE_PATH/$DUMP_TARGET
_dir=$(ssh -qn $_opt $1 mktemp -dqp $SAVE_PATH 2>/dev/null)
_ret=$?
if [ $_ret -ne 0 ]; then
perror_exit "Could not create temporary directory on $DUMP_TARGET:$SAVE_PATH. Make sure user has write permission on destination"
fi
ssh -qn $_opt $1 rmdir $_dir

return 0
}

#Function: get_fs_size
#$1=dump target
get_fs_size() {
local _mnt=$(get_mntpoint_from_target $1)
echo -n $(df -P "${_mnt}/$SAVE_PATH"|tail -1|awk '{print $4}')
}

#Function: get_raw_size
#$1=dump target
get_raw_size() {
echo -n $(fdisk -s "$1")
}

#Function: check_size
#$1: dump type string ('raw', 'fs', 'ssh')
#$2: dump target
check_size() {
local avail memtotal

memtotal=$(awk '/MemTotal/{print $2}' /proc/meminfo)
case "$1" in
raw)
avail=$(get_raw_size "$2")
;;
ssh)
avail=$(get_ssh_size "$2")
;;
fs)
avail=$(get_fs_size "$2")
;;
*)
return
esac

if [ $? -ne 0 ]; then
perror_exit "Check dump target size failed"
fi

if [ $avail -lt $memtotal ]; then
echo "Warning: There might not be enough space to save a vmcore."
echo " The size of $2 should be greater than $memtotal kilo bytes."
fi
}

# $1: core_collector config value
verify_core_collector() {
if grep -q "^raw" $conf_file && [ "${1%% *}" != "makedumpfile" ]; then
echo "Warning: specifying a non-makedumpfile core collector, you will have to recover the vmcore manually."
fi
if is_ssh_dump_target || is_raw_dump_target; then
if [ "${1%% *}" = "makedumpfile" ]; then
! strstr "$1" "-F" && {
perror_exit "The specified dump target needs makedumpfile \"-F\" option."
}
fi
fi
}

add_mount() {
local _mnt=$(to_mount "$1")

if [ $? -ne 0 ]; then
exit 1
fi

add_dracut_mount "$_mnt"
}

# get_maj_min <device>
# Prints the major and minor of a device node.
# Example:
# $ get_maj_min /dev/sda2
# 8:2
get_maj_min() {
local _dev
_dev=$(stat -L -c '$((0x%t)):$((0x%T))' "$1" 2>/dev/null)
_dev=$(eval "echo $_dev")
echo $_dev
}

# ugly workaround for the lvm design
# There is no volume group device,
# so, there are no slave devices for volume groups.
# Logical volumes only have the slave devices they really live on,
# but you cannot create the logical volume without the volume group.
# And the volume group might be bigger than the devices the LV needs.
check_vol_slaves() {
local _lv _vg _pv
for i in /dev/mapper/*; do
_lv=$(get_maj_min $i)
if [[ $_lv = $2 ]]; then
_vg=$(lvm lvs --noheadings -o vg_name $i 2>/dev/null)
# strip space
_vg=$(echo $_vg)
if [[ $_vg ]]; then
for _pv in $(lvm vgs --noheadings -o pv_name "$_vg" 2>/dev/null)
do
check_block_and_slaves $1 $(get_maj_min $_pv) && return 0
done
fi
fi
done
return 1
}

# Walk all the slave relationships for a given block device.
# Stop when our helper function returns success
# $1 = function to call on every found block device
# $2 = block device in major:minor format
check_block_and_slaves() {
local _x
[[ -b /dev/block/$2 ]] || return 1 # Not a block device? So sorry.
"$1" $2 && return
check_vol_slaves "$@" && return 0
if [[ -f /sys/dev/block/$2/../dev ]]; then
check_block_and_slaves $1 $(cat "/sys/dev/block/$2/../dev") && return 0
fi
[[ -d /sys/dev/block/$2/slaves ]] || return 1
for _x in /sys/dev/block/$2/slaves/*/dev; do
[[ -f $_x ]] || continue
check_block_and_slaves $1 $(cat "$_x") && return 0
done
return 1
}

#handle the case user does not specify the dump target explicitly
handle_default_dump_target()
{
local _target
local _mntpoint

is_user_configured_dump_target && return

check_save_path_fs $SAVE_PATH

_mntpoint=$(get_mntpoint_from_path $SAVE_PATH)
_target=$(get_target_from_path $SAVE_PATH)

if is_atomic && is_bind_mount $_mntpoint; then
SAVE_PATH=${SAVE_PATH##"$_mntpoint"}
# the real dump path in the 2nd kernel, if the mount point is bind mounted.
SAVE_PATH=$(get_bind_mount_directory $_mntpoint)/$SAVE_PATH
_mntpoint=$(get_mntpoint_from_target $_target)

# the absolute path in the 1st kernel
SAVE_PATH=$_mntpoint/$SAVE_PATH
fi

SAVE_PATH=${SAVE_PATH##"$_mntpoint"}
add_mount "$_target"
check_size fs $_target
}

get_override_resettable()
{
local override_resettable

override_resettable=$(grep "^override_resettable" $conf_file)
if [ -n "$override_resettable" ]; then
OVERRIDE_RESETTABLE=$(echo $override_resettable | cut -d' ' -f2)
if [ "$OVERRIDE_RESETTABLE" != "0" ] && [ "$OVERRIDE_RESETTABLE" != "1" ];then
perror_exit "override_resettable value $OVERRIDE_RESETTABLE is invalid"
fi
fi
}


# $1: function name
for_each_block_target()
{
local dev majmin

for dev in $(get_kdump_targets); do
[ -b "$dev" ] || continue
majmin=$(get_maj_min $dev)
check_block_and_slaves $1 $majmin && return 1
done

return 0
}



#judge if a specific device with $1 is unresettable
#return false if unresettable.
is_unresettable()
{
local path="/sys/$(udevadm info --query=all --path=/sys/dev/block/$1 | awk '/^P:/ {print $2}' | sed -e 's/\(cciss[0-9]\+\/\).*/\1/g' -e 's/\/block\/.*$//')/resettable"
local resettable=1

if [ -f "$path" ]
then
resettable="$(cat $path)"
[ $resettable -eq 0 -a "$OVERRIDE_RESETTABLE" -eq 0 ] && {
local device=$(udevadm info --query=all --path=/sys/dev/block/$1 | awk -F= '/DEVNAME/{print $2}')
echo "Error: Can not save vmcore because device $device is unresettable"
return 0
}
fi

return 1
}

#check if machine is resettable.
#return true if resettable
check_resettable()
{
local _ret _target

get_override_resettable

for_each_block_target is_unresettable
_ret=$?

[ $_ret -eq 0 ] && return

return 1
}

# $1: maj:min
is_crypt()
{
local majmin=$1 dev line ID_FS_TYPE=""

line=$(udevadm info --query=property --path=/sys/dev/block/$majmin \
| grep "^ID_FS_TYPE")
eval "$line"
[[ "$ID_FS_TYPE" = "crypto_LUKS" ]] && {
dev=$(udevadm info --query=all --path=/sys/dev/block/$majmin | awk -F= '/DEVNAME/{print $2}')
echo "Device $dev is encrypted."
return 0
}
return 1
}

check_crypt()
{
local _ret _target

for_each_block_target is_crypt
_ret=$?

[ $_ret -eq 0 ] && return

return 1
}

if ! check_resettable; then
exit 1
fi

if ! check_crypt; then
echo "Warning: Encrypted device is in dump path. User will prompted for password during second kernel boot."
fi

# firstly get right SSH_KEY_LOCATION
keyfile=$(awk '/^sshkey/ {print $2}' $conf_file)
if [ -f "$keyfile" ]; then
# canonicalize the path
SSH_KEY_LOCATION=$(/usr/bin/readlink -m $keyfile)
fi

if [ "$(uname -m)" = "s390x" ]; then
add_dracut_module "znet"
fi

while read config_opt config_val;
do
# remove inline comments after the end of a directive.
config_val=$(strip_comments $config_val)
case "$config_opt" in
extra_modules)
extra_modules="$extra_modules $config_val"
;;
ext[234]|xfs|btrfs|minix|nfs)
if ! findmnt $config_val >/dev/null; then
perror_exit "Dump target $config_val is probably not mounted."
fi

_absolute_save_path=$(make_absolute_save_path $config_val)
_mntpoint=$(get_mntpoint_from_path $_absolute_save_path)
if is_atomic && is_bind_mount $_mntpoint; then
SAVE_PATH=${_absolute_save_path##"$_mntpoint"}
# the real dump path in the 2nd kernel, if the mount point is bind mounted.
SAVE_PATH=$(get_bind_mount_directory $_mntpoint)/$SAVE_PATH
fi

add_mount "$config_val"
check_save_path_fs $_absolute_save_path
check_size fs $config_val
;;
raw)
#checking raw disk writable
dd if=$config_val count=1 of=/dev/null > /dev/null 2>&1 || {
perror_exit "Bad raw disk $config_val"
}
_praw=$(kdump_get_persistent_dev $config_val "raw")
if [ $? -ne 0 ]; then
exit 1
fi
add_dracut_arg "--device" "$_praw"
check_size raw $config_val
;;
ssh)
if strstr "$config_val" "@";
then
check_size ssh $config_val
mkdir_save_path_ssh $config_val
add_dracut_module "ssh-client"
add_dracut_sshkey "$SSH_KEY_LOCATION"
else
perror_exit "Bad ssh dump target $config_val"
fi
;;
core_collector)
verify_core_collector "$config_val"
;;
dracut_args)
add_dracut_arg $config_val
;;
*)
if [ -n $(echo $config_opt | grep "^#.*$") ]
then
continue
fi
;;
esac
done < $conf_file

handle_default_dump_target

if [ -n "$extra_modules" ]
then
add_dracut_arg "--add-drivers" "$extra_modules"
fi

if ! is_fadump_capable; then
# The 2nd rootfs mount stays behind the normal dump target mount,
# so it doesn't affect the logic of check_dump_fs_modified().
is_dump_to_rootfs && add_mount "$(to_dev_name $(get_root_fs_device))"

add_dracut_arg "--no-hostonly-default-device"
fi

dracut "${dracut_args[@]}" "$@"
_rc=$?
sync
exit $_rc

33
SOURCES/mkdumprd.8

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
.TH MKDUMRD 8 "Fri Feb 9 2007"
.SH NAME
mkdumprd \- creates initial ramdisk images for kdump crash recovery
.SH SYNOPSIS
\fBmkdumprd\fR [OPTION]

.SH DESCRIPTION
\fBmkdumprd\fR creates an initial ram file system for use in conjunction with
the booting of a kernel within the kdump framework for crash recovery.
\fBmkdumprds\fR purpose is to create an initial ram filesystem capable of copying
the crashed systems vmcore image to a location specified in \fI/etc/kdump.conf

\fBmkdumprd\fR interrogates the running system to understand what modules need to
be loaded in the initramfs (based on configuration retrieved from
\fI/etc/kdump.conf)\fR

\fBmkdumprd\fR add a new \fBdracut\fR module 99kdumpbase and use \fBdracut\fR
utility to generate the initramfs.

\fBmkdumprd\fR was not intended for casual use outside of the service
initialization script for the kdump utility, and should not be run manually. If
you require a custom kdump initramfs image, it is suggested that you use the
kdump service infrastructure to create one, and then manually unpack, modify and
repack the image.


.SH OPTIONS
.TP
All options here are passed to dracut directly, please refer \fBdracut\fR docs
for the info.

.SH "SEE ALSO"
.BR dracut (8)

128
SOURCES/supported-kdump-targets.txt

@ -0,0 +1,128 @@ @@ -0,0 +1,128 @@
Supported Kdump Targets

This document try to list all supported kdump targets, and those supported
or unknown/tech-preview targets, this can help users to decide whether a dump
solution is available.

Dump Target support status
==========================
This section tries to come up with some kind of guidelines in terms of
what dump targets are supported/not supported. Whatever is listed here
is not binding in any manner. It is just sharing of current understanding
and if something is not right, this section needs to be edited.

Following are 3 lists. First one contains supported targets. These are
generic configurations which should work and some configuration most
likely has worked in testing. Second list is known unsupported targets.
These targets we know either don't work or we don't support. And third
list is unknown/tech-preview. We either don't yet know the status of kdump
on these targets or these are under tech-preview.

Note, these lists are not set in stone and can be changed at any point of
time. Also these lists might not be complete. We will add/remove items to
it as we get more testing information. Also, there are many corner cases
which can't possibly be listed. For example in general we might be
supporting software iscsi but there might be some configurations of it
which don't work.

So if any target is listed in supported section, it does not mean it works
in all possible configurations. It just means that in common configurations
it should work but there can be issues with particular configurations which
are not supported. As we come to know of particular issues, we will keep on
updating lists accordingly.


Supported Dump targets
----------------------
storage:
LVM volume (no thinp)
FC disks (qla2xxx, lpfc, bnx2fc, bfa)
software initiator based iSCSI
software RAID (mdraid)
hardware RAID (cciss, hpsa, megaraid_sas, mpt2sas, aacraid)
SCSI/SATA disks
iSCSI HBA (all offload)
hardware FCoE (qla2xxx, lpfc, bfa)
software FCoE (bnx2fc, fcoe/ixgbe) (Extra configuration required,
please read "Note on FCoE" section below)

network:
Hardware using kernel modules: (tg3, igb, ixgbe, sfc, e1000e, bna,
cnic, netxen_nic, qlge, bnx2x, bnx, qlcnic, be2net, enic,
virtio-net, ixgbevf, igbvf)
protocol: ipv4
bonding
vlan
bridge
team
vlan tagged bonding
bridge over bond/team/vlan

hypervisor:
kvm
xen (Supported in select configurations only)

filesystem:
ext[234]
xfs
nfs

firmware:
BIOS
UEFI

hypervisor:
VMWare ESXi 4.1 and 5.1
Hyper-V 2012 R2 (RHEL Gen1 UP Guest only)

Unsupported Dump targets
------------------------
storage:
BIOS RAID
Thin provisioning volume
Software iSCSI with iBFT (bnx2i, cxgb3i, cxgb4i)
Software iSCSI with hybrid (be2iscsi)
FCoE
legacy IDE
glusterfs
gfs2/clvm/halvm

network:
hardware using kernel modules: (sfc SRIOV, cxgb4vf, pch_gbe)
protocol: ipv6
wireless
Infiniband (IB)
vlan over bridge/team

filesystem:
btrfs

Unknown/tech-preview
--------------------
storage:
PCI Express based SSDs

hypervisor:
Hyper-V 2008
Hyper-V 2012


Note on FCoE
=====================
If you are trying to dump to a software FCoE target, you may encounter OOM
issue, because some software FCoE requires more memory to work. In such case,
you may need to increase the kdump reserved memory size in "crashkernel="
kernel parameter.

By default, RHEL systems have "crashkernel=auto" in kernel boot arguments.
The auto reserved memory size is designed to balance the coverage of use cases
and an acceptable memory overhead, so not every use case could fit in, software
FCoE is one of the case.

For hardware FCoE, kdump should work naturally as firmware will do the
initialization job. The capture kernel and kdump tools will run just fine.

Useful Links
============
[1] RHEL6: Enabling kdump for full-virt (HVM) Xen DomU
(https://access.redhat.com/knowledge/solutions/92943)

1844
SPECS/kexec-tools.spec

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save