diff --git a/SOURCES/60-kdump.install b/SOURCES/60-kdump.install
index 0a3b40e..5b0e021 100755
--- a/SOURCES/60-kdump.install
+++ b/SOURCES/60-kdump.install
@@ -2,17 +2,23 @@
 
 COMMAND="$1"
 KERNEL_VERSION="$2"
-BOOT_DIR_ABS="$3"
+KDUMP_INITRD_DIR_ABS="$3"
 KERNEL_IMAGE="$4"
 
 if ! [[ ${KERNEL_INSTALL_MACHINE_ID-x} ]]; then
     exit 0
 fi
 
-if [[ -d "$BOOT_DIR_ABS" ]]; then
+if [[ -d "$KDUMP_INITRD_DIR_ABS" ]]; then
     KDUMP_INITRD="initrdkdump"
 else
-    BOOT_DIR_ABS="/boot"
+    # If `KDUMP_BOOTDIR` is not writable, then the kdump
+    # initrd must have been placed at `/var/lib/kdump`
+    if [[ ! -w "/boot" ]]; then
+        KDUMP_INITRD_DIR_ABS="/var/lib/kdump"
+    else
+        KDUMP_INITRD_DIR_ABS="/boot"
+    fi
     KDUMP_INITRD="initramfs-${KERNEL_VERSION}kdump.img"
 fi
 
@@ -23,7 +29,7 @@ case "$COMMAND" in
         # and managed by kdump service
         ;;
     remove)
-        rm -f -- "$BOOT_DIR_ABS/$KDUMP_INITRD"
+        rm -f -- "$KDUMP_INITRD_DIR_ABS/$KDUMP_INITRD"
         ret=$?
         ;;
 esac
diff --git a/SOURCES/98-kexec.rules.ppc64 b/SOURCES/98-kexec.rules.ppc64
index 1a91220..a1c00a9 100644
--- a/SOURCES/98-kexec.rules.ppc64
+++ b/SOURCES/98-kexec.rules.ppc64
@@ -1,15 +1,22 @@
-SUBSYSTEM=="cpu", ACTION=="online", GOTO="kdump_reload"
-SUBSYSTEM=="memory", ACTION=="online", GOTO="kdump_reload"
-SUBSYSTEM=="memory", ACTION=="offline", GOTO="kdump_reload"
+SUBSYSTEM=="cpu", ACTION=="online", GOTO="kdump_reload_cpu"
+SUBSYSTEM=="memory", ACTION=="online", GOTO="kdump_reload_mem"
+SUBSYSTEM=="memory", ACTION=="offline", GOTO="kdump_reload_mem"
 
 GOTO="kdump_reload_end"
 
-LABEL="kdump_reload"
-
 # If kdump is not loaded, calling kdump-udev-throttle will end up
 # doing nothing, but systemd-run will always generate extra logs for
 # each call, so trigger the kdump-udev-throttler only if kdump
 # service is active to avoid unnecessary logs
+
+LABEL="kdump_reload_mem"
+
 RUN+="/bin/sh -c '/usr/bin/systemctl is-active kdump.service || exit 0; /usr/bin/systemd-run --quiet --no-block /usr/lib/udev/kdump-udev-throttler'"
 
+GOTO="kdump_reload_end"
+
+LABEL="kdump_reload_cpu"
+
+RUN+="/bin/sh -c '/usr/bin/systemctl is-active kdump.service || exit 0; ! test -f /sys/kernel/fadump_enabled || cat /sys/kernel/fadump_enabled | grep 0  || exit 0; /usr/bin/systemd-run --quiet --no-block /usr/lib/udev/kdump-udev-throttler'"
+
 LABEL="kdump_reload_end"
diff --git a/SOURCES/dracut-kdump.sh b/SOURCES/dracut-kdump.sh
index 2497218..c7cf528 100755
--- a/SOURCES/dracut-kdump.sh
+++ b/SOURCES/dracut-kdump.sh
@@ -136,7 +136,7 @@ dump_ssh()
         fi
         _exitcode=$?
     else
-        $CORE_COLLECTOR /proc/vmcore | ssh $_opt $_host "dd bs=512 of=$_dir/vmcore-incomplete"
+        $CORE_COLLECTOR /proc/vmcore | ssh $_opt $_host "umask 0077 && dd bs=512 of=$_dir/vmcore-incomplete"
         _exitcode=$?
         _vmcore="vmcore.flat"
     fi
@@ -218,7 +218,7 @@ save_vmcore_dmesg_ssh() {
     local _location=$4
 
     dinfo "saving vmcore-dmesg.txt to $_location:$_path"
-    $_dmesg_collector /proc/vmcore | ssh $_opts $_location "dd of=$_path/vmcore-dmesg-incomplete.txt"
+    $_dmesg_collector /proc/vmcore | ssh $_opts $_location "umask 0077 && dd of=$_path/vmcore-dmesg-incomplete.txt"
     _exitcode=$?
 
     if [ $_exitcode -eq 0 ]; then
diff --git a/SOURCES/dracut-module-setup.sh b/SOURCES/dracut-module-setup.sh
index 917afed..dafdad6 100755
--- a/SOURCES/dracut-module-setup.sh
+++ b/SOURCES/dracut-module-setup.sh
@@ -119,12 +119,122 @@ kdump_setup_dns() {
     done < "/etc/resolv.conf"
 }
 
+# $1: repeat times
+# $2: string to be repeated
+# $3: separator
+repeatedly_join_str() {
+    local _count="$1"
+    local _str="$2"
+    local _separator="$3"
+    local i _res
+
+    if [[ "$_count" -le 0 ]]; then
+        echo -n ""
+        return
+    fi
+
+    i=0
+    _res="$_str"
+    ((_count--))
+
+    while [[ "$i" -lt "$_count" ]]; do
+        ((i++))
+        _res="${_res}${_separator}${_str}"
+    done
+    echo -n "$_res"
+}
+
+# $1: prefix
+# $2: ipv6_flag="-6" indicates it's IPv6
+# Given a prefix, calculate the netmask (equivalent of "ipcalc -m")
+# by concatenating three parts,
+#  1) the groups with all bits set 1
+#  2) a group with partial bits set to 0
+#  3) the groups with all bits set to 0
+cal_netmask_by_prefix() {
+    local _prefix="$1"
+    local _ipv6_flag="$2" _ipv6
+    local _bits_per_octet=8
+    local _count _res _octets_per_group _octets_total _seperator _total_groups
+    local _max_group_value _max_group_value_repr _bits_per_group _tmp _zero_bits
+
+    if [[ "$_ipv6_flag" == "-6" ]]; then
+        _ipv6=1
+    else
+        _ipv6=0
+    fi
+
+    if [[ "$_prefix" -lt 0  ||  "$_prefix" -gt 128 ]] || \
+        ( ((!_ipv6)) && [[ "$_prefix" -gt 32 ]] ); then
+        derror "Bad prefix:$_prefix for calculating netmask"
+        exit 1
+    fi
+
+    if ((_ipv6)); then
+        _octets_per_group=2
+        _octets_total=16
+        _seperator=":"
+    else
+        _octets_per_group=1
+        _octets_total=4
+        _seperator="."
+    fi
+
+    _total_groups=$((_octets_total/_octets_per_group))
+    _bits_per_group=$((_octets_per_group * _bits_per_octet))
+    _max_group_value=$(((1 << _bits_per_group) - 1))
+
+    if ((_ipv6)); then
+        _max_group_value_repr=$(printf "%x" $_max_group_value)
+    else
+        _max_group_value_repr="$_max_group_value"
+    fi
+
+    _count=$((_prefix/_octets_per_group/_bits_per_octet))
+    _first_part=$(repeatedly_join_str "$_count" "$_max_group_value_repr" "$_seperator")
+    _res="$_first_part"
+
+    _tmp=$((_octets_total*_bits_per_octet-_prefix))
+    _zero_bits=$(expr $_tmp % $_bits_per_group)
+    if [[ "$_zero_bits" -ne 0 ]]; then
+        _second_part=$((_max_group_value >> _zero_bits << _zero_bits))
+        if ((_ipv6)); then
+            _second_part=$(printf "%x" $_second_part)
+        fi
+        ((_count++))
+        if [[ -z "$_first_part" ]]; then
+            _res="$_second_part"
+        else
+            _res="${_first_part}${_seperator}${_second_part}"
+        fi
+    fi
+
+    _count=$((_total_groups-_count))
+    if [[ "$_count" -eq 0 ]]; then
+        echo -n "$_res"
+        return
+    fi
+
+    if ((_ipv6)) && [[ "$_count" -gt 1 ]] ; then
+        # use condensed notion for IPv6
+        _third_part=":"
+    else
+        _third_part=$(repeatedly_join_str "$_count" "0" "$_seperator")
+    fi
+
+    if [[ -z "$_res" ]] && ((!_ipv6)) ; then
+        echo -n "${_third_part}"
+    else
+        echo -n "${_res}${_seperator}${_third_part}"
+    fi
+}
+
 #$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
+    local _netdev="$1" _srcaddr="$2" kdumpnic="$3" _ipv6_flag
+    local _netmask _gateway _ipaddr _target _nexthop _prefix
 
     _ipaddr=$(ip addr show dev $_netdev permanent | awk "/ $_srcaddr\/.* /{print \$2}")
 
@@ -142,7 +252,12 @@ kdump_static_ip() {
             _srcaddr="[$_srcaddr]"
             _gateway="[$_gateway]"
         else
-            _netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2)
+            _prefix=$(cut -d'/' -f2 <<< "$_ipaddr")
+            _netmask=$(cal_netmask_by_prefix "$_prefix" "$_ipv6_flag")
+            if [[ "$?" -ne 0 ]]; then
+                derror "Failed to calculate netmask for $_ipaddr"
+                exit 1
+            fi
         fi
         echo -n "${_srcaddr}::${_gateway}:${_netmask}::"
     fi
@@ -155,7 +270,7 @@ kdump_static_ip() {
             _target="[$_target]"
             _nexthop="[$_nexthop]"
         fi
-        echo "rd.route=$_target:$_nexthop:$_netdev"
+        echo "rd.route=$_target:$_nexthop:$kdumpnic"
     done >> ${initdir}/etc/cmdline.d/45route-static.conf
 }
 
@@ -276,6 +391,37 @@ kdump_setup_vlan() {
     fi
 }
 
+# find online znet device
+# return ifname (_netdev)
+# code reaped from the list_configured function of
+# https://github.com/hreinecke/s390-tools/blob/master/zconf/znetconf
+find_online_znet_device() {
+	local CCWGROUPBUS_DEVICEDIR="/sys/bus/ccwgroup/devices"
+	local NETWORK_DEVICES d ifname ONLINE
+
+	[ ! -d "$CCWGROUPBUS_DEVICEDIR" ] && return
+	NETWORK_DEVICES=$(find $CCWGROUPBUS_DEVICEDIR)
+	for d in $NETWORK_DEVICES
+	do
+		[ ! -f "$d/online" ] && continue
+		read ONLINE < $d/online
+		if [ $ONLINE -ne 1 ]; then
+			continue
+		fi
+		# determine interface name, if there (only for qeth and if
+		# device is online)
+		if [ -f $d/if_name ]
+		then
+			read ifname < $d/if_name
+		elif [ -d $d/net ]
+		then
+			ifname=$(ls $d/net/)
+		fi
+		[ -n "$ifname" ] && break
+	done
+	echo -n "$ifname"
+}
+
 # setup s390 znet cmdline
 # $1: netdev name
 kdump_setup_znet() {
@@ -293,14 +439,22 @@ kdump_setup_znet() {
 # 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
+    local _static _proto _ip_conf _ip_opts _ifname_opts kdumpnic
     local _netmac=$(kdump_get_mac_addr $_netdev)
+    local _znet_netdev
 
-    if [ "$(uname -m)" = "s390x" ]; then
-        kdump_setup_znet $_netdev
+    kdumpnic=$(kdump_setup_ifname $_netdev)
+
+    _znet_netdev=$(find_online_znet_device)
+    if [[ -n "$_znet_netdev" ]]; then
+        $(kdump_setup_znet "$_znet_netdev")
+        if [[ $? != 0 ]]; then
+            derror "Failed to set up znet"
+            exit 1
+        fi
     fi
 
-    _static=$(kdump_static_ip $_netdev $_srcaddr)
+    _static=$(kdump_static_ip $_netdev $_srcaddr $kdumpnic)
     if [ -n "$_static" ]; then
         _proto=none
     elif is_ipv6_address $_srcaddr; then
@@ -310,7 +464,7 @@ kdump_setup_netdev() {
     fi
 
     _ip_conf="${initdir}/etc/cmdline.d/40ip.conf"
-    _ip_opts=" ip=${_static}$(kdump_setup_ifname $_netdev):${_proto}"
+    _ip_opts=" ip=${_static}$kdumpnic:${_proto}"
 
     # dracut doesn't allow duplicated configuration for same NIC, even they're exactly the same.
     # so we have to avoid adding duplicates
@@ -330,7 +484,7 @@ kdump_setup_netdev() {
     elif kdump_is_vlan "$_netdev"; then
         kdump_setup_vlan "$_netdev"
     else
-        _ifname_opts=" ifname=$(kdump_setup_ifname $_netdev):$_netmac"
+        _ifname_opts=" ifname=$kdumpnic:$_netmac"
         echo "$_ifname_opts" >> $_ip_conf
     fi
 
@@ -829,6 +983,7 @@ install() {
     inst "/sbin/vmcore-dmesg" "/sbin/vmcore-dmesg"
     inst "/usr/bin/printf" "/sbin/printf"
     inst "/usr/bin/logger" "/sbin/logger"
+    inst "/usr/bin/chmod" "/sbin/chmod"
     inst "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh"
     inst "/lib/kdump/kdump-lib-initramfs.sh" "/lib/kdump-lib-initramfs.sh"
     inst "/lib/kdump/kdump-logger.sh" "/lib/kdump-logger.sh"
diff --git a/SOURCES/fadump-howto.txt b/SOURCES/fadump-howto.txt
index 5360f3d..433e9a6 100644
--- a/SOURCES/fadump-howto.txt
+++ b/SOURCES/fadump-howto.txt
@@ -224,12 +224,16 @@ Things to remember:
    dracut_args --add "network"
 
 4) If FADump is configured to capture vmcore to a remote dump target using SSH
-   or NFS protocol, the network interface is renamed to kdump-<interface-name>
-   if <interface-name> is generic, for example, *eth#, or net#. This problem
-   occurs because the vmcore capture scripts in the initial RAM disk (initrd)
-   add the kdump- prefix to the network interface name to secure persistent
-   naming. As the same initrd is used for production kernel boot, the interface
-   name is changed for the production kernel too.
+   or NFS protocol, the corresponding network interface '<interface-name>' is
+   renamed to 'kdump-<interface-name>', if it is generic (like *eth# or net#).
+   It happens because vmcore capture scripts in the initial RAM disk (initrd)
+   add the 'kdump-' prefix to the network interface name to secure persistent
+   naming. And as capture kernel and production kernel use the same initrd in
+   case of FADump, the interface name is changed for the production kernel too.
+   This is likely to impact network configuration setup for production kernel.
+   So, it is recommended to use a non-generic name for a network interface,
+   before setting up FADump to capture vmcore to a remote dump target based on
+   that network interface, to avoid running into network configuration issues.
 
 Dump Triggering methods:
 
diff --git a/SOURCES/kdump-lib-initramfs.sh b/SOURCES/kdump-lib-initramfs.sh
index a43c7dd..e030fe6 100755
--- a/SOURCES/kdump-lib-initramfs.sh
+++ b/SOURCES/kdump-lib-initramfs.sh
@@ -111,6 +111,7 @@ save_log()
     if command -v journalctl > /dev/null; then
         journalctl -ab >> $KDUMP_LOG_FILE
     fi
+    chmod 600 $KDUMP_LOG_FILE
 }
 
 # dump_fs <mount point>
@@ -171,6 +172,7 @@ save_vmcore_dmesg_fs() {
     _exitcode=$?
     if [ $_exitcode -eq 0 ]; then
         mv ${_path}/vmcore-dmesg-incomplete.txt ${_path}/vmcore-dmesg.txt
+        chmod 600 ${_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
diff --git a/SOURCES/kdump-lib.sh b/SOURCES/kdump-lib.sh
index 8ae8617..67ee10e 100755
--- a/SOURCES/kdump-lib.sh
+++ b/SOURCES/kdump-lib.sh
@@ -617,11 +617,16 @@ is_secure_boot_enforced()
     local secure_boot_file setup_mode_file
     local secure_boot_byte setup_mode_byte
 
-    # On powerpc, os-secureboot-enforcing DT property indicates whether secureboot
-    # is enforced. Return success, if it is found.
+    # On powerpc, secure boot is enforced if:
+    #   host secure boot: /ibm,secure-boot/os-secureboot-enforcing DT property exists
+    #   guest secure boot: /ibm,secure-boot >= 2
     if [ -f /proc/device-tree/ibm,secureboot/os-secureboot-enforcing ]; then
 		return 0
     fi
+    if [ -f /proc/device-tree/ibm,secure-boot ] && \
+       [ $(lsprop /proc/device-tree/ibm,secure-boot | tail -1) -ge 2 ]; then
+		return 0
+    fi
 
     # Detect secure boot on x86 and arm64
     secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null)
@@ -689,7 +694,7 @@ prepare_kdump_bootinfo()
     local boot_imglist boot_dirlist boot_initrdlist curr_kver="$(uname -r)"
     local machine_id
 
-    if [ -z "$KDUMP_KERNELVER"]; then
+    if [ -z "$KDUMP_KERNELVER" ]; then
         KDUMP_KERNELVER="$(uname -r)"
     fi
 
@@ -724,20 +729,30 @@ prepare_kdump_bootinfo()
     boot_initrdlist="initramfs-$KDUMP_KERNELVER.img initrd"
     for initrd in $boot_initrdlist; do
         if [ -f "$KDUMP_BOOTDIR/$initrd" ]; then
-            DEFAULT_INITRD="$KDUMP_BOOTDIR/$initrd"
+            defaut_initrd_base="$initrd"
+            DEFAULT_INITRD="$KDUMP_BOOTDIR/$defaut_initrd_base"
             break
         fi
     done
 
-    # Get kdump initrd from default initrd filename
+    # Create kdump initrd basename from default initrd basename
     # initramfs-5.7.9-200.fc32.x86_64.img => initramfs-5.7.9-200.fc32.x86_64kdump.img
     # initrd => initrdkdump
-    if [[ -z "$DEFAULT_INITRD" ]]; then
-        KDUMP_INITRD=${KDUMP_BOOTDIR}/initramfs-${KDUMP_KERNELVER}kdump.img
-    elif [[ $(basename $DEFAULT_INITRD) == *.* ]]; then
-        KDUMP_INITRD=${DEFAULT_INITRD%.*}kdump.${DEFAULT_INITRD##*.}
+    if [[ -z "$defaut_initrd_base" ]]; then
+        kdump_initrd_base=initramfs-${KDUMP_KERNELVER}kdump.img
+    elif [[ $defaut_initrd_base == *.* ]]; then
+        kdump_initrd_base=${defaut_initrd_base%.*}kdump.${DEFAULT_INITRD##*.}
+    else
+        kdump_initrd_base=${defaut_initrd_base}kdump
+    fi
+
+    # Place kdump initrd in `/var/lib/kdump` if `KDUMP_BOOTDIR` not writable
+    if [[ ! -w "$KDUMP_BOOTDIR" ]];then
+        var_target_initrd_dir="/var/lib/kdump"
+        mkdir -p "$var_target_initrd_dir"
+        KDUMP_INITRD="$var_target_initrd_dir/$kdump_initrd_base"
     else
-        KDUMP_INITRD=${DEFAULT_INITRD}kdump
+        KDUMP_INITRD="$KDUMP_BOOTDIR/$kdump_initrd_base"
     fi
 }
 
@@ -819,3 +834,192 @@ prepare_cmdline()
 
     echo ${cmdline}
 }
+
+#get system memory size in the unit of GB
+get_system_size()
+{
+    result=$(cat /proc/iomem  | grep "System RAM" | awk -F ":" '{ print $1 }' | tr [:lower:] [:upper:] | paste -sd+)
+    result="+$result"
+    # replace '-' with '+0x' and '+' with '-0x'
+    sum=$( echo $result | sed -e 's/-/K0x/g' | sed -e 's/+/-0x/g' | sed -e 's/K/+/g' )
+    size=$(printf "%d\n" $(($sum)))
+
+    # in MB unit
+    let size=$size/1024/1024
+    # since RHEL-8.5 kernel round up total memory to 128M, so should user space
+    let size=($size+127)/128
+    let size=$size*128
+    # in GB unit
+    let size=$size/1024
+
+    echo $size
+}
+
+get_recommend_size()
+{
+    local mem_size=$1
+    local _ck_cmdline=$2
+    local OLDIFS="$IFS"
+
+    last_sz=""
+    last_unit=""
+
+    start=${_ck_cmdline: :1}
+    if [ $mem_size -lt $start ]; then
+        echo "0M"
+        return
+    fi
+    IFS=','
+    for i in $_ck_cmdline; do
+        end=$(echo $i | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $1 }')
+        recommend=$(echo $i | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $2 }')
+        size=${end: : -1}
+        unit=${end: -1}
+        if [ $unit == 'T' ]; then
+            let size=$size*1024
+        fi
+        if [ $mem_size -lt $size ]; then
+            echo $recommend
+            IFS="$OLDIFS"
+            return
+        fi
+    done
+    IFS="$OLDIFS"
+}
+
+# return recommended size based on current system RAM size
+kdump_get_arch_recommend_size()
+{
+    if ! [[ -r "/proc/iomem" ]] ; then
+        echo "Error, can not access /proc/iomem."
+        return 1
+    fi
+    arch=$(lscpu | grep Architecture | awk -F ":" '{ print $2 }' | tr [:lower:] [:upper:])
+
+    if [ $arch == "X86_64" ] || [ $arch == "S390X" ]; then
+        ck_cmdline="1G-4G:160M,4G-64G:192M,64G-1T:256M,1T-:512M"
+    elif [ $arch == "AARCH64" ]; then
+        ck_cmdline="2G-:448M"
+    elif [ $arch == "PPC64LE" ]; then
+        if is_fadump_capable; then
+            ck_cmdline="4G-16G:768M,16G-64G:1G,64G-128G:2G,128G-1T:4G,1T-2T:6G,2T-4T:12G,4T-8T:20G,8T-16T:36G,16T-32T:64G,32T-64T:128G,64T-:180G"
+        else
+            ck_cmdline="2G-4G:384M,4G-16G:512M,16G-64G:1G,64G-128G:2G,128G-:4G"
+        fi
+    fi
+
+    ck_cmdline=$(echo $ck_cmdline | sed -e 's/-:/-102400T:/g')
+    sys_mem=$(get_system_size)
+    result=$(get_recommend_size $sys_mem "$ck_cmdline")
+    echo $result
+    return 0
+}
+
+# Print all underlying crypt devices of a block device
+# print nothing if device is not on top of a crypt device
+# $1: the block device to be checked in maj:min format
+get_luks_crypt_dev()
+{
+    [[ -b /dev/block/$1 ]] || return 1
+
+    local _type=$(eval "$(blkid -u filesystem,crypto -o export -- /dev/block/$1); echo \$TYPE")
+    [[ $_type == "crypto_LUKS" ]] && echo $1
+
+    for _x in /sys/dev/block/$1/slaves/*; do
+        [[ -f $_x/dev ]] || continue
+        [[ $_x/subsystem -ef /sys/class/block ]] || continue
+        get_luks_crypt_dev "$(< "$_x/dev")"
+    done
+}
+
+# kdump_get_maj_min <device>
+# Prints the major and minor of a device node.
+# Example:
+# $ get_maj_min /dev/sda2
+# 8:2
+kdump_get_maj_min() {
+    local _majmin
+    _majmin="$(stat -L -c '%t:%T' "$1" 2> /dev/null)"
+    printf "%s" "$((0x${_majmin%:*})):$((0x${_majmin#*:}))"
+}
+
+get_all_kdump_crypt_dev()
+{
+    local _dev _crypt
+
+    for _dev in $(get_block_dump_target); do
+        _crypt=$(get_luks_crypt_dev $(kdump_get_maj_min "$_dev"))
+        [[ -n "$_crypt" ]] && echo $_crypt
+    done
+}
+
+check_vmlinux()
+{
+    # Use readelf to check if it's a valid ELF
+    readelf -h $1 &>/dev/null || return 1
+}
+
+get_vmlinux_size()
+{
+    local size=0
+
+    while read _type _offset _virtaddr _physaddr _fsize _msize _flg _aln; do
+        size=$(( $size + $_msize ))
+    done <<< $(readelf -l -W $1 | grep "^  LOAD" 2>/dev/stderr)
+
+    echo $size
+}
+
+try_decompress()
+{
+    # The obscure use of the "tr" filter is to work around older versions of
+    # "grep" that report the byte offset of the line instead of the pattern.
+
+    # Try to find the header ($1) and decompress from here
+    for pos in `tr "$1\n$2" "\n$2=" < "$4" | grep -abo "^$2"`
+    do
+        if ! type -P $3 > /dev/null; then
+            ddebug "Signiature detected but '$3' is missing, skip this decompressor"
+            break
+        fi
+
+        pos=${pos%%:*}
+        tail -c+$pos "$img" | $3 > $5 2> /dev/null
+        if check_vmlinux $5; then
+            ddebug "Kernel is extracted with '$3'"
+            return 0
+        fi
+    done
+
+    return 1
+}
+
+# Borrowed from linux/scripts/extract-vmlinux
+get_kernel_size()
+{
+    # Prepare temp files:
+    local img=$1 tmp=$(mktemp /tmp/vmlinux-XXX)
+    trap "rm -f $tmp" 0
+
+    # Try to check if it's a vmlinux already
+    check_vmlinux $img && get_vmlinux_size $img && return 0
+
+    # That didn't work, so retry after decompression.
+    try_decompress '\037\213\010' xy    gunzip    $img $tmp || \
+    try_decompress '\3757zXZ\000' abcde unxz      $img $tmp || \
+    try_decompress 'BZh'          xy    bunzip2   $img $tmp || \
+    try_decompress '\135\0\0\0'   xxx   unlzma    $img $tmp || \
+    try_decompress '\211\114\132' xy    'lzop -d' $img $tmp || \
+    try_decompress '\002!L\030'   xxx   'lz4 -d'  $img $tmp || \
+    try_decompress '(\265/\375'   xxx   unzstd    $img $tmp
+
+    # Finally check for uncompressed images or objects:
+    [[ $? -eq 0 ]] && get_vmlinux_size $tmp && return 0
+
+    # Fallback to use iomem
+    local _size=0
+    for _seg in $(cat /proc/iomem  | grep -E "Kernel (code|rodata|data|bss)" | cut -d ":" -f 1); do
+	    _size=$(( $_size + 0x${_seg#*-} - 0x${_seg%-*} ))
+    done
+    echo $_size
+}
diff --git a/SOURCES/kdump-migrate-action.sh b/SOURCES/kdump-migrate-action.sh
new file mode 100755
index 0000000..c516639
--- /dev/null
+++ b/SOURCES/kdump-migrate-action.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+systemctl is-active kdump
+if [ $? -ne 0 ]; then
+        exit 0
+fi
+
+/usr/lib/kdump/kdump-restart.sh
diff --git a/SOURCES/kdump-restart.sh b/SOURCES/kdump-restart.sh
new file mode 100644
index 0000000..a9ecfc1
--- /dev/null
+++ b/SOURCES/kdump-restart.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+export PATH="$PATH:/usr/bin:/usr/sbin"
+
+exec >>/var/log/kdump-migration.log 2>&1
+
+echo "kdump: Partition Migration detected. Rebuilding initramfs image to reload."
+/usr/bin/kdumpctl rebuild
+/usr/bin/kdumpctl reload
diff --git a/SOURCES/kdump.sysconfig.s390x b/SOURCES/kdump.sysconfig.s390x
index 3f75b76..efa0394 100644
--- a/SOURCES/kdump.sysconfig.s390x
+++ b/SOURCES/kdump.sysconfig.s390x
@@ -17,7 +17,7 @@ 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 quiet log_buf_len swiotlb"
+KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet log_buf_len swiotlb prot_virt"
 
 # This variable lets us append arguments to the current kdump commandline
 # after processed by KDUMP_COMMANDLINE_REMOVE
diff --git a/SOURCES/kdumpctl b/SOURCES/kdumpctl
index ef86571..e8a7a3a 100755
--- a/SOURCES/kdumpctl
+++ b/SOURCES/kdumpctl
@@ -151,8 +151,8 @@ rebuild_kdump_initrd()
 
 rebuild_initrd()
 {
-	if [[ ! -w "$KDUMP_BOOTDIR" ]];then
-		derror "$KDUMP_BOOTDIR does not have write permission. Can not rebuild $TARGET_INITRD"
+	if [[ ! -w $(dirname $TARGET_INITRD) ]];then
+		derror "$(dirname $TARGET_INITRD) does not have write permission. Cannot rebuild $TARGET_INITRD"
 		return 1
 	fi
 
@@ -237,12 +237,7 @@ restore_default_initrd()
 check_config()
 {
 	local -A _opt_rec
-	while read config_opt config_val; do
-		if [ -z "$config_val" ]; then
-			derror "Invalid kdump config value for option $config_opt"
-			return 1
-		fi
-
+	while read -r config_opt config_val; do
 		case "$config_opt" in
 		dracut_args)
 			if [[ $config_val == *--mount* ]]; then
@@ -269,12 +264,20 @@ check_config()
 			derror "Deprecated kdump config option: $config_opt. Refer to kdump.conf manpage for alternatives."
 			return 1
 			;;
+		'')
+			continue
+			;;
 		*)
 			derror "Invalid kdump config option $config_opt"
 			return 1
 			;;
 		esac
 
+		if [[ -z "$config_val" ]]; then
+			derror "Invalid kdump config value for option '$config_opt'"
+			return 1
+		fi
+
 		if [ -n "${_opt_rec[$config_opt]}" ]; then
 			if [ $config_opt == _target ]; then
 				derror "More than one dump targets specified"
@@ -643,6 +646,35 @@ check_rebuild()
 	return $?
 }
 
+# On ppc64le LPARs, the keys trusted by firmware do not end up in
+# .builtin_trusted_keys. So instead, add the key to the .ima keyring
+function load_kdump_kernel_key()
+{
+	# this is only called inside is_secure_boot_enforced,
+	# no need to retest
+
+        # this is only required if DT /ibm,secure-boot is a file.
+        # if it is a dir, we are on OpenPower and don't need this.
+        if ! [ -f /proc/device-tree/ibm,secure-boot ]; then
+                return
+        fi
+
+        KDUMP_KEY_ID=$(cat /usr/share/doc/kernel-keys/$KDUMP_KERNELVER/kernel-signing-ppc.cer |
+                        keyctl padd asymmetric kernelkey-$RANDOM %:.ima)
+}
+
+# remove a previously loaded key. There's no real security implication
+# to leaving it around, we choose to do this because it makes it easier
+# to be idempotent and so as to reduce the potential for confusion.
+function remove_kdump_kernel_key()
+{
+	if [ -z "$KDUMP_KEY_ID" ]; then
+		return
+	fi
+
+	keyctl unlink $KDUMP_KEY_ID %:.ima
+}
+
 # Load the kdump kernel specified in /etc/sysconfig/kdump
 # If none is specified, try to load a kdump kernel with the same version
 # as the currently running kernel.
@@ -659,6 +691,7 @@ load_kdump()
 	if is_secure_boot_enforced; then
 		dinfo "Secure Boot is enabled. Using kexec file based syscall."
 		KEXEC_ARGS="$KEXEC_ARGS -s"
+		load_kdump_kernel_key
 	fi
 
 	ddebug "$KEXEC $KEXEC_ARGS $standard_kexec_args --command-line=$KDUMP_COMMANDLINE --initrd=$TARGET_INITRD $KDUMP_KERNEL"
@@ -680,6 +713,8 @@ load_kdump()
 	set +x
 	exec 2>&12 12>&-
 
+	remove_kdump_kernel_key
+
 	if [ $ret == 0 ]; then
 		dinfo "kexec: loaded kdump kernel"
 		return 0
@@ -1214,6 +1249,97 @@ rebuild() {
 	return $?
 }
 
+do_estimate() {
+	local kdump_mods
+	local -A large_mods
+	local baseline
+	local kernel_size mod_size initrd_size baseline_size runtime_size reserved_size estimated_size recommended_size
+	local size_mb=$(( 1024 * 1024 ))
+
+	setup_initrd
+	if [ ! -f "$TARGET_INITRD" ]; then
+		derror "kdumpctl estimate: kdump initramfs is not built yet."
+		exit 1
+	fi
+
+	kdump_mods="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/loaded-kernel-modules.txt | tr '\n' ' ')"
+	baseline=$(kdump_get_arch_recommend_size)
+	if [[ "${baseline: -1}" == "M" ]]; then
+		baseline=${baseline%M}
+	elif [[ "${baseline: -1}" == "G" ]]; then
+		baseline=$(( ${baseline%G} * 1024 ))
+	elif [[ "${baseline: -1}" == "T" ]]; then
+		baseline=$(( ${baseline%Y} * 1048576 ))
+	fi
+
+	# The default value when using crashkernel=auto
+	baseline_size=$((baseline * size_mb))
+	# Current reserved crashkernel size
+	reserved_size=$(cat /sys/kernel/kexec_crash_size)
+	# A pre-estimated value for userspace usage and kernel
+	# runtime allocation, 64M should good for most cases
+	runtime_size=$((64 * size_mb))
+	# Kernel image size
+	kernel_size=$(get_kernel_size "$KDUMP_KERNEL")
+	# Kdump initramfs size
+	initrd_size=$(du -b "$TARGET_INITRD" | awk '{print $1}')
+	# Kernel modules static size after loaded
+	mod_size=0
+	while read -r _name _size _; do
+		if [[ ! " $kdump_mods " == *" $_name "* ]]; then
+			continue
+		fi
+		mod_size=$((mod_size + _size))
+
+		# Mark module with static size larger than 2M as large module
+		if [[ $((_size / size_mb)) -ge 1 ]]; then
+			large_mods[$_name]=$_size
+		fi
+	done <<< "$(< /proc/modules)"
+
+	# Extra memory usage required for LUKS2 decryption
+	crypt_size=0
+	for _dev in $(get_all_kdump_crypt_dev); do
+		_crypt_info=$(cryptsetup luksDump "/dev/block/$_dev")
+		[[ $(echo "$_crypt_info" | sed -n "s/^Version:\s*\(.*\)/\1/p" ) == "2" ]] || continue
+		for _mem in $(echo "$_crypt_info" | sed -n "s/\sMemory:\s*\(.*\)/\1/p" | sort -n ); do
+			crypt_size=$((crypt_size + _mem * 1024))
+			break
+		done
+	done
+	[[ $crypt_size -ne 0 ]] && echo -e "Encrypted kdump target requires extra memory, assuming using the keyslot with minimun memory requirement\n"
+
+	estimated_size=$((kernel_size + mod_size + initrd_size + runtime_size + crypt_size))
+	if [[ $baseline_size -gt $estimated_size ]]; then
+		recommended_size=$baseline_size
+	else
+		recommended_size=$estimated_size
+	fi
+
+	echo "Reserved crashkernel:    $((reserved_size / size_mb))M"
+	echo "Recommended crashkernel: $((recommended_size / size_mb))M"
+	echo
+	echo "Kernel image size:   $((kernel_size / size_mb))M"
+	echo "Kernel modules size: $((mod_size / size_mb))M"
+	echo "Initramfs size:      $((initrd_size / size_mb))M"
+	echo "Runtime reservation: $((runtime_size / size_mb))M"
+	[[ $crypt_size -ne 0 ]] && \
+	echo "LUKS required size:  $((crypt_size / size_mb))M"
+	echo -n "Large modules:"
+	if [[ "${#large_mods[@]}" -eq 0 ]]; then
+		echo " <none>"
+	else
+		echo ""
+		for _mod in "${!large_mods[@]}"; do
+			echo "    $_mod: ${large_mods[$_mod]}"
+		done
+	fi
+
+	if [[ $reserved_size -lt $recommended_size ]]; then
+		echo "WARNING: Current crashkernel size is lower than recommended size $((recommended_size / size_mb))M."
+	fi
+}
+
 if [ ! -f "$KDUMP_CONFIG_FILE" ]; then
 	derror "Error: No kdump config file found!"
 	exit 1
@@ -1269,8 +1395,11 @@ main ()
 	  showmem)
 		show_reserved_mem
 		;;
+	  estimate)
+		do_estimate
+		;;
 	  *)
-		dinfo $"Usage: $0 {start|stop|status|restart|reload|rebuild|propagate|showmem}"
+		dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|propagate|showmem}"
 		exit 1
 	esac
 }
diff --git a/SOURCES/kdumpctl.8 b/SOURCES/kdumpctl.8
index ae97af7..a32a972 100644
--- a/SOURCES/kdumpctl.8
+++ b/SOURCES/kdumpctl.8
@@ -44,6 +44,11 @@ impossible to use password authentication during kdump.
 .TP
 .I showmem
 Prints the size of reserved memory for crash kernel in megabytes.
+.TP
+.I estimate
+Estimate a suitable crashkernel value for current machine. This is a
+best-effort estimate. It will print a recommanded crashkernel value
+based on current kdump setup, and list some details of memory usage.
 
 .SH "SEE ALSO"
 .BR kdump.conf (5),
diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch
new file mode 100644
index 0000000..631d039
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch
@@ -0,0 +1,177 @@
+From 3422e1d6bc3511c5af9cb05ba74ad97dd93ffd7f Mon Sep 17 00:00:00 2001
+From: Julien Thierry <jthierry@redhat.com>
+Date: Tue, 24 Nov 2020 10:45:24 +0000
+Subject: [PATCH] [PATCH 1/2] Add --dry-run option to prevent writing the
+ dumpfile
+
+Add a --dry-run option to run all operations without writing the
+dump to the output file.
+
+Signed-off-by: Julien Thierry <jthierry@redhat.com>
+Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
+---
+ makedumpfile.8 |  6 ++++++
+ makedumpfile.c | 37 ++++++++++++++++++++++++++++++-------
+ makedumpfile.h |  2 ++
+ print_info.c   |  3 +++
+ 4 files changed, 41 insertions(+), 7 deletions(-)
+
+diff --git a/makedumpfile-1.6.8/makedumpfile.8 b/makedumpfile-1.6.8/makedumpfile.8
+index b68a7e3..5e902cd 100644
+--- a/makedumpfile-1.6.8/makedumpfile.8
++++ b/makedumpfile-1.6.8/makedumpfile.8
+@@ -637,6 +637,12 @@ Show the version of makedumpfile.
+ Only check whether the command-line parameters are valid or not, and exit.
+ Preferable to be given as the first parameter.
+ 
++.TP
++\fB\-\-dry-run\fR
++Do not write the output dump file while still performing operations specified
++by other options.
++This option cannot be used with the --dump-dmesg, --reassemble and -g options.
++
+ .SH ENVIRONMENT VARIABLES
+ 
+ .TP 8
+diff --git a/makedumpfile-1.6.8/makedumpfile.c b/makedumpfile-1.6.8/makedumpfile.c
+index ecd63fa..8c80c49 100644
+--- a/makedumpfile-1.6.8/makedumpfile.c
++++ b/makedumpfile-1.6.8/makedumpfile.c
+@@ -1372,6 +1372,8 @@ open_dump_file(void)
+ 	if (info->flag_flatten) {
+ 		fd = STDOUT_FILENO;
+ 		info->name_dumpfile = filename_stdout;
++	} else if (info->flag_dry_run) {
++		fd = -1;
+ 	} else if ((fd = open(info->name_dumpfile, open_flags,
+ 	    S_IRUSR|S_IWUSR)) < 0) {
+ 		ERRMSG("Can't open the dump file(%s). %s\n",
+@@ -4711,6 +4713,9 @@ write_and_check_space(int fd, void *buf, size_t buf_size, char *file_name)
+ {
+ 	int status, written_size = 0;
+ 
++	if (info->flag_dry_run)
++		return TRUE;
++
+ 	while (written_size < buf_size) {
+ 		status = write(fd, buf + written_size,
+ 				   buf_size - written_size);
+@@ -4748,13 +4753,12 @@ write_buffer(int fd, off_t offset, void *buf, size_t buf_size, char *file_name)
+ 		}
+ 		if (!write_and_check_space(fd, &fdh, sizeof(fdh), file_name))
+ 			return FALSE;
+-	} else {
+-		if (lseek(fd, offset, SEEK_SET) == failed) {
+-			ERRMSG("Can't seek the dump file(%s). %s\n",
+-			    file_name, strerror(errno));
+-			return FALSE;
+-		}
++	} else if (!info->flag_dry_run &&
++		    lseek(fd, offset, SEEK_SET) == failed) {
++		ERRMSG("Can't seek the dump file(%s). %s\n", file_name, strerror(errno));
++		return FALSE;
+ 	}
++
+ 	if (!write_and_check_space(fd, buf, buf_size, file_name))
+ 		return FALSE;
+ 
+@@ -9112,7 +9116,7 @@ close_dump_memory(void)
+ void
+ close_dump_file(void)
+ {
+-	if (info->flag_flatten)
++	if (info->flag_flatten || info->flag_dry_run)
+ 		return;
+ 
+ 	if (close(info->fd_dumpfile) < 0)
+@@ -10985,6 +10989,11 @@ check_param_for_generating_vmcoreinfo(int argc, char *argv[])
+ 
+ 		return FALSE;
+ 
++	if (info->flag_dry_run) {
++		MSG("--dry-run cannot be used with -g.\n");
++		return FALSE;
++	}
++
+ 	return TRUE;
+ }
+ 
+@@ -11029,6 +11038,11 @@ check_param_for_reassembling_dumpfile(int argc, char *argv[])
+ 	    || info->flag_exclude_xen_dom || info->flag_split)
+ 		return FALSE;
+ 
++	if (info->flag_dry_run) {
++		MSG("--dry-run cannot be used with --reassemble.\n");
++		return FALSE;
++	}
++
+ 	if ((info->splitting_info
+ 	    = malloc(sizeof(struct splitting_info) * info->num_dumpfile))
+ 	    == NULL) {
+@@ -11057,6 +11071,11 @@ check_param_for_creating_dumpfile(int argc, char *argv[])
+ 	    || (info->flag_read_vmcoreinfo && info->name_xen_syms))
+ 		return FALSE;
+ 
++	if (info->flag_dry_run && info->flag_dmesg) {
++		MSG("--dry-run cannot be used with --dump-dmesg.\n");
++		return FALSE;
++	}
++
+ 	if (info->flag_flatten && info->flag_split)
+ 		return FALSE;
+ 
+@@ -11520,6 +11539,7 @@ static struct option longopts[] = {
+ 	{"work-dir", required_argument, NULL, OPT_WORKING_DIR},
+ 	{"num-threads", required_argument, NULL, OPT_NUM_THREADS},
+ 	{"check-params", no_argument, NULL, OPT_CHECK_PARAMS},
++	{"dry-run", no_argument, NULL, OPT_DRY_RUN},
+ 	{0, 0, 0, 0}
+ };
+ 
+@@ -11686,6 +11706,9 @@ main(int argc, char *argv[])
+ 			info->flag_check_params = TRUE;
+ 			message_level = DEFAULT_MSG_LEVEL;
+ 			break;
++		case OPT_DRY_RUN:
++			info->flag_dry_run = TRUE;
++			break;
+ 		case '?':
+ 			MSG("Commandline parameter is invalid.\n");
+ 			MSG("Try `makedumpfile --help' for more information.\n");
+diff --git a/makedumpfile-1.6.8/makedumpfile.h b/makedumpfile-1.6.8/makedumpfile.h
+index 5f50080..4c4222c 100644
+--- a/makedumpfile-1.6.8/makedumpfile.h
++++ b/makedumpfile-1.6.8/makedumpfile.h
+@@ -1322,6 +1322,7 @@ struct DumpInfo {
+ 	int		flag_vmemmap;        /* kernel supports vmemmap address space */
+ 	int		flag_excludevm;      /* -e - excluding unused vmemmap pages */
+ 	int		flag_use_count;      /* _refcount is named _count in struct page */
++	int		flag_dry_run;        /* do not create a vmcore file */
+ 	unsigned long	vaddr_for_vtop;      /* virtual address for debugging */
+ 	long		page_size;           /* size of page */
+ 	long		page_shift;
+@@ -2425,6 +2426,7 @@ struct elf_prstatus {
+ #define OPT_NUM_THREADS         OPT_START+16
+ #define OPT_PARTIAL_DMESG       OPT_START+17
+ #define OPT_CHECK_PARAMS        OPT_START+18
++#define OPT_DRY_RUN             OPT_START+19
+ 
+ /*
+  * Function Prototype.
+diff --git a/makedumpfile-1.6.8/print_info.c b/makedumpfile-1.6.8/print_info.c
+index e0c38b4..d2b0cb7 100644
+--- a/makedumpfile-1.6.8/print_info.c
++++ b/makedumpfile-1.6.8/print_info.c
+@@ -308,6 +308,9 @@ print_usage(void)
+ 	MSG("      the crashkernel range, then calculates the page number of different kind per\n");
+ 	MSG("      vmcoreinfo. So currently /proc/kcore need be specified explicitly.\n");
+ 	MSG("\n");
++	MSG("  [--dry-run]:\n");
++	MSG("      This option runs makedumpfile without writting output dump file.\n");
++	MSG("\n");
+ 	MSG("  [-D]:\n");
+ 	MSG("      Print debugging message.\n");
+ 	MSG("\n");
+-- 
+2.29.2
+
diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch
new file mode 100644
index 0000000..5e935f0
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch
@@ -0,0 +1,107 @@
+From 6f3e75a558ed50d6ff0b42e3f61c099b2005b7bb Mon Sep 17 00:00:00 2001
+From: Julien Thierry <jthierry@redhat.com>
+Date: Tue, 24 Nov 2020 10:45:25 +0000
+Subject: [PATCH] [PATCH 2/2] Add shorthand --show-stats option to show report
+ stats
+
+Provide shorthand --show-stats option to enable report messages
+without needing to set a particular value for message-level.
+
+Signed-off-by: Julien Thierry <jthierry@redhat.com>
+Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
+---
+ makedumpfile.8 | 5 +++++
+ makedumpfile.c | 9 ++++++++-
+ makedumpfile.h | 1 +
+ print_info.c   | 7 ++++++-
+ 4 files changed, 20 insertions(+), 2 deletions(-)
+
+diff --git a/makedumpfile-1.6.8/makedumpfile.8 b/makedumpfile-1.6.8/makedumpfile.8
+index 5e902cd..dcca2dd 100644
+--- a/makedumpfile-1.6.8/makedumpfile.8
++++ b/makedumpfile-1.6.8/makedumpfile.8
+@@ -643,6 +643,11 @@ Do not write the output dump file while still performing operations specified
+ by other options.
+ This option cannot be used with the --dump-dmesg, --reassemble and -g options.
+ 
++.TP
++\fB\-\-show-stats\fR
++Display report messages. This is an alternative to enabling bit 4 in the level
++provided to --message-level.
++
+ .SH ENVIRONMENT VARIABLES
+ 
+ .TP 8
+diff --git a/makedumpfile-1.6.8/makedumpfile.c b/makedumpfile-1.6.8/makedumpfile.c
+index 8c80c49..ba0003a 100644
+--- a/makedumpfile-1.6.8/makedumpfile.c
++++ b/makedumpfile-1.6.8/makedumpfile.c
+@@ -11540,13 +11540,14 @@ static struct option longopts[] = {
+ 	{"num-threads", required_argument, NULL, OPT_NUM_THREADS},
+ 	{"check-params", no_argument, NULL, OPT_CHECK_PARAMS},
+ 	{"dry-run", no_argument, NULL, OPT_DRY_RUN},
++	{"show-stats", no_argument, NULL, OPT_SHOW_STATS},
+ 	{0, 0, 0, 0}
+ };
+ 
+ int
+ main(int argc, char *argv[])
+ {
+-	int i, opt, flag_debug = FALSE;
++	int i, opt, flag_debug = FALSE, flag_show_stats = FALSE;
+ 
+ 	if ((info = calloc(1, sizeof(struct DumpInfo))) == NULL) {
+ 		ERRMSG("Can't allocate memory for the pagedesc cache. %s.\n",
+@@ -11709,6 +11710,9 @@ main(int argc, char *argv[])
+ 		case OPT_DRY_RUN:
+ 			info->flag_dry_run = TRUE;
+ 			break;
++		case OPT_SHOW_STATS:
++			flag_show_stats = TRUE;
++			break;
+ 		case '?':
+ 			MSG("Commandline parameter is invalid.\n");
+ 			MSG("Try `makedumpfile --help' for more information.\n");
+@@ -11718,6 +11722,9 @@ main(int argc, char *argv[])
+ 	if (flag_debug)
+ 		message_level |= ML_PRINT_DEBUG_MSG;
+ 
++	if (flag_show_stats)
++		message_level |= ML_PRINT_REPORT_MSG;
++
+ 	if (info->flag_check_params)
+ 		/* suppress debugging messages */
+ 		message_level = DEFAULT_MSG_LEVEL;
+diff --git a/makedumpfile-1.6.8/makedumpfile.h b/makedumpfile-1.6.8/makedumpfile.h
+index 4c4222c..2fcb62e 100644
+--- a/makedumpfile-1.6.8/makedumpfile.h
++++ b/makedumpfile-1.6.8/makedumpfile.h
+@@ -2427,6 +2427,7 @@ struct elf_prstatus {
+ #define OPT_PARTIAL_DMESG       OPT_START+17
+ #define OPT_CHECK_PARAMS        OPT_START+18
+ #define OPT_DRY_RUN             OPT_START+19
++#define OPT_SHOW_STATS          OPT_START+20
+ 
+ /*
+  * Function Prototype.
+diff --git a/makedumpfile-1.6.8/print_info.c b/makedumpfile-1.6.8/print_info.c
+index d2b0cb7..ad4184e 100644
+--- a/makedumpfile-1.6.8/print_info.c
++++ b/makedumpfile-1.6.8/print_info.c
+@@ -309,7 +309,12 @@ print_usage(void)
+ 	MSG("      vmcoreinfo. So currently /proc/kcore need be specified explicitly.\n");
+ 	MSG("\n");
+ 	MSG("  [--dry-run]:\n");
+-	MSG("      This option runs makedumpfile without writting output dump file.\n");
++	MSG("      Do not write the output dump file while still performing operations specified\n");
++	MSG("      by other options.  This option cannot be used with --dump-dmesg, --reassemble\n");
++	MSG("      and -g options.\n");
++	MSG("\n");
++	MSG("  [--show-stats]:\n");
++	MSG("      Set message-level to print report messages\n");
+ 	MSG("\n");
+ 	MSG("  [-D]:\n");
+ 	MSG("      Print debugging message.\n");
+-- 
+2.29.2
+
diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch
new file mode 100644
index 0000000..337288e
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch
@@ -0,0 +1,59 @@
+From 0ef2ca6c9fa2f61f217a4bf5d7fd70f24e12b2eb Mon Sep 17 00:00:00 2001
+From: Kazuhito Hagio <k-hagio-ab@nec.com>
+Date: Thu, 4 Feb 2021 16:29:06 +0900
+Subject: [PATCH] [PATCH] Show write byte size in report messages
+
+Show write byte size in report messages.  This value can be different
+from the size of the actual file because of some holes on dumpfile
+data structure.
+
+  $ makedumpfile --show-stats -l -d 1 vmcore dump.ld1
+  ...
+  Total pages     : 0x0000000000080000
+  Write bytes     : 377686445
+  ...
+  # ls -l dump.ld1
+  -rw------- 1 root root 377691573 Feb  4 16:28 dump.ld1
+
+Note that this value should not be used with /proc/kcore to determine
+how much disk space is needed for crash dump, because the real memory
+usage when a crash occurs can vary widely.
+
+Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
+---
+ makedumpfile.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/makedumpfile-1.6.8/makedumpfile.c b/makedumpfile-1.6.8/makedumpfile.c
+index fcd766b..894c88e 100644
+--- a/makedumpfile-1.6.8/makedumpfile.c
++++ b/makedumpfile-1.6.8/makedumpfile.c
+@@ -48,6 +48,8 @@ char filename_stdout[] = FILENAME_STDOUT;
+ static unsigned long long	cache_hit;
+ static unsigned long long	cache_miss;
+ 
++static unsigned long long	write_bytes;
++
+ static void first_cycle(mdf_pfn_t start, mdf_pfn_t max, struct cycle *cycle)
+ {
+ 	cycle->start_pfn = round(start, info->pfn_cyclic);
+@@ -4715,6 +4717,8 @@ write_and_check_space(int fd, void *buf, size_t buf_size, char *file_name)
+ {
+ 	int status, written_size = 0;
+ 
++	write_bytes += buf_size;
++
+ 	if (info->flag_dry_run)
+ 		return TRUE;
+ 
+@@ -10002,6 +10006,7 @@ print_report(void)
+ 	REPORT_MSG("Memory Hole     : 0x%016llx\n", pfn_memhole);
+ 	REPORT_MSG("--------------------------------------------------\n");
+ 	REPORT_MSG("Total pages     : 0x%016llx\n", info->max_mapnr);
++	REPORT_MSG("Write bytes     : %llu\n", write_bytes);
+ 	REPORT_MSG("\n");
+ 	REPORT_MSG("Cache hit: %lld, miss: %lld", cache_hit, cache_miss);
+ 	if (cache_hit + cache_miss)
+-- 
+2.29.2
+
diff --git a/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch b/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch
new file mode 100644
index 0000000..c6eb40f
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch
@@ -0,0 +1,60 @@
+From 38d921a2ef50ebd36258097553626443ffe27496 Mon Sep 17 00:00:00 2001
+From: Coiby Xu <coxu@redhat.com>
+Date: Tue, 15 Jun 2021 18:26:31 +0800
+Subject: [PATCH] check for invalid physical address of /proc/kcore
+ when finding max_paddr
+
+Kernel commit 464920104bf7adac12722035bfefb3d772eb04d8 ("/proc/kcore:
+update physical address for kcore ram and text") sets an invalid paddr
+(0xffffffffffffffff = -1) for PT_LOAD segments of not direct mapped
+regions:
+
+  $ readelf -l /proc/kcore
+  ...
+  Program Headers:
+    Type           Offset             VirtAddr           PhysAddr
+                   FileSiz            MemSiz              Flags  Align
+    NOTE           0x0000000000000120 0x0000000000000000 0x0000000000000000
+                   0x0000000000002320 0x0000000000000000         0x0
+    LOAD           0x1000000000010000 0xd000000000000000 0xffffffffffffffff
+                                                         ^^^^^^^^^^^^^^^^^^
+                   0x0001f80000000000 0x0001f80000000000  RWE    0x10000
+
+makedumpfile uses max_paddr to calculate the number of sections for
+sparse memory model thus wrong number is obtained based on max_paddr
+(-1).  This error could lead to the failure of copying /proc/kcore
+for RHEL-8.5 on ppc64le machine [1]:
+
+  $ makedumpfile /proc/kcore vmcore1
+  get_mem_section: Could not validate mem_section.
+  get_mm_sparsemem: Can't get the address of mem_section.
+
+  makedumpfile Failed.
+
+Let's check if the phys_start of the segment is a valid physical
+address to fix this problem.
+
+[1] https://bugzilla.redhat.com/show_bug.cgi?id=1965267
+
+Reported-by: Xiaoying Yan <yiyan@redhat.com>
+Signed-off-by: Coiby Xu <coxu@redhat.com>
+---
+ elf_info.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/makedumpfile-1.6.8/elf_info.c b/makedumpfile-1.6.8/elf_info.c
+index e8affb7..bc24083 100644
+--- a/makedumpfile-1.6.8/elf_info.c
++++ b/makedumpfile-1.6.8/elf_info.c
+@@ -628,7 +628,7 @@ get_max_paddr(void)
+ 
+ 	for (i = 0; i < num_pt_loads; i++) {
+ 		pls = &pt_loads[i];
+-		if (max_paddr < pls->phys_end)
++		if (pls->phys_start != NOT_PADDR && max_paddr < pls->phys_end)
+ 			max_paddr = pls->phys_end;
+ 	}
+ 	return max_paddr;
+-- 
+2.29.2
+
diff --git a/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch b/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch
new file mode 100644
index 0000000..9180dc6
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch
@@ -0,0 +1,43 @@
+From 9a6f589d99dcef114c89fde992157f5467028c8f Mon Sep 17 00:00:00 2001
+From: Tao Liu <ltao@redhat.com>
+Date: Fri, 18 Jun 2021 18:28:04 +0800
+Subject: [PATCH] check for invalid physical address of /proc/kcore
+ when making ELF dumpfile
+
+Previously when executing makedumpfile with -E option against
+/proc/kcore, makedumpfile will fail:
+
+  # makedumpfile -E -d 31 /proc/kcore kcore.dump
+  ...
+  write_elf_load_segment: Can't convert physaddr(ffffffffffffffff) to an offset.
+
+  makedumpfile Failed.
+
+It's because /proc/kcore contains PT_LOAD program headers which have
+physaddr (0xffffffffffffffff).  With -E option, makedumpfile will
+try to convert the physaddr to an offset and fails.
+
+Skip the PT_LOAD program headers which have such physaddr.
+
+Signed-off-by: Tao Liu <ltao@redhat.com>
+Signed-off-by: Kazuhito Hagio <k-hagio-ab@nec.com>
+---
+ makedumpfile.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/makedumpfile-1.6.8/makedumpfile.c b/makedumpfile-1.6.8/makedumpfile.c
+index 894c88e..fcb571f 100644
+--- a/makedumpfile-1.6.8/makedumpfile.c
++++ b/makedumpfile-1.6.8/makedumpfile.c
+@@ -7764,7 +7764,7 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page)
+ 		if (!get_phdr_memory(i, &load))
+ 			return FALSE;
+ 
+-		if (load.p_type != PT_LOAD)
++		if (load.p_type != PT_LOAD || load.p_paddr == NOT_PADDR)
+ 			continue;
+ 
+ 		off_memory= load.p_offset;
+-- 
+2.29.2
+
diff --git a/SOURCES/mkdumprd b/SOURCES/mkdumprd
index 6e923fe..3c2fb5d 100644
--- a/SOURCES/mkdumprd
+++ b/SOURCES/mkdumprd
@@ -226,7 +226,7 @@ check_user_configured_target()
 
     # For user configured target, use $SAVE_PATH as the dump path within the target
     if [ ! -d "$_mnt/$SAVE_PATH" ]; then
-        perror_exit "Dump path \"$SAVE_PATH\" does not exist in dump target \"$_target\""
+        perror_exit "Dump path \"$_mnt/$SAVE_PATH\" does not exist in dump target \"$_target\""
     fi
 
     check_size fs "$_target"
@@ -305,7 +305,6 @@ get_override_resettable()
     fi
 }
 
-
 # $1: function name
 for_each_block_target()
 {
@@ -320,8 +319,6 @@ for_each_block_target()
     return 0
 }
 
-
-
 #judge if a specific device with $1 is unresettable
 #return false if unresettable.
 is_unresettable()
@@ -358,32 +355,15 @@ check_resettable()
     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}')
-        derror "Device $dev is encrypted."
-        return 0
-    }
-    return 1
-}
-
 check_crypt()
 {
-    local _ret _target
-
-    for_each_block_target is_crypt
-    _ret=$?
-
-    [ $_ret -eq 0 ] && return
+    local _dev
 
-    return 1
+    for _dev in $(get_kdump_targets); do
+        if [[ -n $(get_luks_crypt_dev "$(get_maj_min "$_dev")") ]]; then
+            derror "Device $_dev is encrypted." && return 1
+        fi
+    done
 }
 
 if ! check_resettable; then
diff --git a/SPECS/kexec-tools.spec b/SPECS/kexec-tools.spec
index 94aa05d..8ab65a9 100644
--- a/SPECS/kexec-tools.spec
+++ b/SPECS/kexec-tools.spec
@@ -1,6 +1,6 @@
 Name: kexec-tools
 Version: 2.0.20
-Release: 45%{?dist}
+Release: 57%{?dist}
 License: GPLv2
 Group: Applications/System
 Summary: The kexec/kdump userspace component
@@ -36,6 +36,8 @@ Source30: kdump.sysconfig.aarch64
 Source31: fadump-howto.txt
 Source32: 60-kdump.install
 Source33: kdump-logger.sh
+Source34: kdump-migrate-action.sh
+Source35: kdump-restart.sh
 
 #######################################
 # These are sources for mkdumpramfs
@@ -52,6 +54,9 @@ Source107: dracut-kdump-emergency.target
 Source108: dracut-early-kdump.sh
 Source109: dracut-early-kdump-module-setup.sh
 
+%ifarch ppc64 ppc64le
+Requires(post): servicelog
+%endif
 Requires(post): systemd-units
 Requires(preun): systemd-units
 Requires(postun): systemd-units
@@ -111,7 +116,11 @@ Patch613: kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch
 
 # Patches 701 onward for makedumpfile
 Patch701: rhelonly-kexec-tools-2.0.20-makedumpfile-arm64-Add-support-for-ARMv8.2-LVA-52-bi.patch
-
+Patch702: kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch
+Patch703: kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch
+Patch704: kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch
+Patch705: kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch
+Patch706: kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch
 
 %description
 kexec-tools provides /usr/sbin/kexec binary that facilitates a new
@@ -141,6 +150,11 @@ tar -z -x -v -f %{SOURCE19}
 %patch612 -p1
 %patch613 -p1
 %patch701 -p1
+%patch702 -p1
+%patch703 -p1
+%patch704 -p1
+%patch705 -p1
+%patch706 -p1
 
 %ifarch ppc
 %define archdef ARCH=ppc
@@ -190,6 +204,7 @@ mkdir -p $RPM_BUILD_ROOT%{_unitdir}
 mkdir -p -m755 $RPM_BUILD_ROOT%{_bindir}
 mkdir -p -m755 $RPM_BUILD_ROOT%{_libdir}
 mkdir -p -m755 $RPM_BUILD_ROOT%{_prefix}/lib/kdump
+mkdir -p -m755 $RPM_BUILD_ROOT%{_sharedstatedir}/kdump
 install -m 755 %{SOURCE1} $RPM_BUILD_ROOT%{_bindir}/kdumpctl
 
 install -m 755 build/sbin/kexec $RPM_BUILD_ROOT/usr/sbin/kexec
@@ -217,6 +232,8 @@ install -m 644 %{SOURCE13} $RPM_BUILD_ROOT%{_udevrulesdir}/98-kexec.rules
 %endif
 %ifarch ppc64 ppc64le
 install -m 644 %{SOURCE14} $RPM_BUILD_ROOT%{_udevrulesdir}/98-kexec.rules
+install -m 755 %{SOURCE34} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-migrate-action.sh
+install -m 755 %{SOURCE35} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-restart.sh
 %endif
 %ifnarch s390x
 install -m 755 %{SOURCE29} $RPM_BUILD_ROOT%{_udevrulesdir}/../kdump-udev-throttler
@@ -269,6 +286,13 @@ mv $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/* $RPM_BUILD_ROOT/%{d
 %systemd_post kdump.service
 
 touch /etc/kdump.conf
+
+%ifarch ppc64 ppc64le
+servicelog_notify --remove --command=/usr/lib/kdump/kdump-migrate-action.sh
+servicelog_notify --add --command=/usr/lib/kdump/kdump-migrate-action.sh --match='refcode="#MIGRATE" and serviceable=0' --type=EVENT --method=pairs_stdin
+%endif
+
+
 # This portion of the script is temporary.  Its only here
 # to fix up broken boxes that require special settings 
 # in /etc/sysconfig/kdump.  It will be removed when 
@@ -296,6 +320,9 @@ fi
 %systemd_postun_with_restart kdump.service
 
 %preun
+%ifarch ppc64 ppc64le
+servicelog_notify --remove --command=/usr/lib/kdump/kdump-migrate-action.sh
+%endif
 # Package removal, not upgrade
 %systemd_preun kdump.service
 
@@ -354,6 +381,7 @@ done
 %dir %{_sysconfdir}/kdump
 %dir %{_sysconfdir}/kdump/pre.d
 %dir %{_sysconfdir}/kdump/post.d
+%dir %{_sharedstatedir}/kdump
 %{_mandir}/man8/kdumpctl.8.gz
 %{_mandir}/man8/kexec.8.gz
 %{_mandir}/man8/makedumpfile.8.gz
@@ -378,6 +406,60 @@ done
 %endif
 
 %changelog
+* Fri Aug 27 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-57
+- kdumpctl: enable secure boot on ppc64le LPARs
+
+* Fri Aug  6 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-56
+- kdumpctl: fix a typo
+
+* Mon Aug  2 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-55
+- kdump/ppc64: migration action registration clean up
+
+* Fri Jul 23 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-54
+- kdump/ppc64: rebuild initramfs image after migration
+- Check the existence of /sys/bus/ccwgroup/devices/*/online beforehand
+- kdump.sysconfig.s390: Remove "prot_virt" from kdump kernel cmdline
+
+* Fri Jul  2 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-53
+- check for invalid physical address of /proc/kcore when making ELF dumpfile
+- check for invalid physical address of /proc/kcore when finding max_paddr
+- fix format issue in find_online_znet_device
+- check the existence of /sys/bus/ccwgroup/devices before trying to find online network device
+- kdump-lib.sh: fix a warning in prepare_kdump_bootinfo()
+
+* Thu Jun 17 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-52
+- Write to `/var/lib/kdump` if $KDUMP_BOOTDIR not writable
+- Iterate /sys/bus/ccwgroup/devices to tell if we should set up rd.znet
+- mkdumprd: display the absolute path of dump location in the check_user_configured_target()
+
+* Wed Jun  2 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-51
+- Stop reloading kdump service on CPU hotplug event for FADump
+- fadump: improve fadump-howto.txt about remote dump target setup
+
+* Tue May 25 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-50
+- rd.route should use the name from kdump_setup_ifname
+- get kdump ifname once in kdump_install_netdev
+
+* Tue May 25 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-49
+- kdump-lib.sh: fix the case if no enough total RAM for kdump  in get_recommend_size()
+
+* Thu May 20 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-48
+- kdumpctl: Add kdumpctl estimate
+- mkdumprd: make use of the new get_luks_crypt_dev helper
+- kdump-lib.sh: introduce a helper to get all crypt dev used by kdump
+- kdump-lib.sh: introduce a helper to get underlying crypt device
+- RHEL-only: keep total memory size coherent to RHEL-only kernel patch
+- Show write byte size in report messages
+- Add shorthand --show-stats option to show report stats
+- Add --dry-run option to prevent writing the dumpfile
+- kdump-lib.sh: introduce functions to return recommened mem size
+
+* Mon May 10 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-47
+- Implement IP netmask calculation to replace "ipcalc -m"
+- kdumpctl: fix check_config error when kdump.conf is empty
+- Fix incorrect vmcore permissions when dumped through ssh
+- Fix incorrect permissions on kdump dmesg file
+
 * Mon Jan 25 2021 Pingfan Liu <piliu@redhat.com> - 2.0.20-45
 - origin/rhel-8.4.0) Revert "Revert "Append both nofail and x-systemd.before to kdump mount target""
 - kdump.conf: add ipv6 example for nfs and ssh dump