basebuilder_pel7x64builder0
6 years ago
85 changed files with 13936 additions and 0 deletions
@ -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" |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
||||
} |
@ -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 |
@ -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. |
@ -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 |
@ -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. |
@ -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 |
||||
} |
@ -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 |
||||
} |
@ -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 |
@ -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) |
@ -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 |
@ -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="" |
@ -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" |
@ -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="" |
@ -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="" |
@ -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 |
@ -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 |
@ -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="" |
@ -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="" |
@ -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) |
@ -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. |
||||
|
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
||||
|
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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 |
||||
|
@ -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) |
||||
|
@ -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 |
@ -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) |
@ -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) |
Loading…
Reference in new issue