diff --git a/.gitignore b/.gitignore
index aa8d011..4114f43 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-SOURCES/eppic_030413.tar.gz
-SOURCES/kdump-anaconda-addon-003-11-g7f70211.tar.gz
+SOURCES/eppic_050615.tar.gz
+SOURCES/kdump-anaconda-addon-003-19-gda64a86.tar.gz
 SOURCES/kexec-tools-2.0.7.tar.xz
 SOURCES/makedumpfile-1.5.7.tar.gz
diff --git a/.kexec-tools.metadata b/.kexec-tools.metadata
index 5ea0345..9edc81a 100644
--- a/.kexec-tools.metadata
+++ b/.kexec-tools.metadata
@@ -1,4 +1,4 @@
-dcdb6d2488c8a31ae95563e2113860ae16256c8f SOURCES/eppic_030413.tar.gz
-41895bf0a59e7359a12d7973a0171337fb69edb0 SOURCES/kdump-anaconda-addon-003-11-g7f70211.tar.gz
+a096c8e0892b559f40b01916aae240652f75b68a SOURCES/eppic_050615.tar.gz
+35161100add54ace94d0966fe45a9e3d5755114c SOURCES/kdump-anaconda-addon-003-19-gda64a86.tar.gz
 56f3c4c829d0078bb705f980e1d9ba22eb9a6246 SOURCES/kexec-tools-2.0.7.tar.xz
 16427d952ce7d0426c8b4aecc92f2960cf7926d3 SOURCES/makedumpfile-1.5.7.tar.gz
diff --git a/SOURCES/dracut-kdump.sh b/SOURCES/dracut-kdump.sh
index dc948d1..4aab205 100755
--- a/SOURCES/dracut-kdump.sh
+++ b/SOURCES/dracut-kdump.sh
@@ -121,9 +121,9 @@ get_host_ip()
     then
         kdumpnic=$(getarg kdumpnic=)
         [ -z "$kdumpnic" ] && echo "kdump: failed to get kdumpnic!" && return 1
-        _host=`ip addr show dev $kdumpnic|grep 'inet '`
+        _host=`ip addr show dev $kdumpnic|grep '[ ]*inet'`
         [ $? -ne 0 ] && echo "kdump: wrong kdumpnic: $kdumpnic" && return 1
-        _host="${_host##*inet }"
+        _host=`echo $_host | head -n 1 | cut -d' ' -f2`
         _host="${_host%%/*}"
         [ -z "$_host" ] && echo "kdump: wrong kdumpnic: $kdumpnic" && return 1
         HOST_IP=$_host
diff --git a/SOURCES/dracut-module-setup.sh b/SOURCES/dracut-module-setup.sh
index eeb348c..5a11a42 100755
--- a/SOURCES/dracut-module-setup.sh
+++ b/SOURCES/dracut-module-setup.sh
@@ -64,29 +64,64 @@ kdump_is_vlan() {
 
 # $1: netdev name
 kdump_setup_dns() {
-    _dnsfile=${initdir}/etc/cmdline.d/42dns.conf
+    local _nameserver _dns
+    local _dnsfile=${initdir}/etc/cmdline.d/42dns.conf
     . /etc/sysconfig/network-scripts/ifcfg-$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 _netmask _gateway
-    local _netdev="$1" _srcaddr="$2"
-    local _ipaddr=$(ip addr show dev $_netdev permanent | \
-                    awk "/ $_srcaddr\/.* $_netdev\$/{print \$2}")
+    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
-       _netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2)
-       _gateway=$(ip route list dev $_netdev | awk '/^default /{print $3}')
-       echo -n "${_srcaddr}::${_gateway}:${_netmask}::"
+        _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 route show | grep -v default | grep "^[[:digit:]].*via.* $_netdev " |\
-    while read line; do
-        echo $line | awk '{printf("rd.route=%s:%s:%s\n", $1, $3, $5)}'
+    /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
 }
 
@@ -261,32 +296,36 @@ kdump_setup_netdev() {
     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
+    local _server _netdev _srcaddr _route _serv_tmp
     local config_val="$1"
 
-    _server=`echo $config_val | sed 's/.*@//' | cut -d':' -f1`
+    _server=$(get_remote_host $config_val)
 
-    _need_dns=`echo $_server|grep "[a-zA-Z]"`
-    [ -n "$_need_dns" ] && _server=`getent hosts $_server|cut -d' ' -f1`
+    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
 
-    _netdev=`/sbin/ip route get to $_server 2>&1`
+    _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
-    if [ -n "`echo $_netdev | grep via`" ]
-    then
-        # we are going to a different subnet
-        _srcaddr=`echo $_netdev|awk '{print $7}'|head -n 1`
-        _netdev=`echo $_netdev|awk '{print $5;}'|head -n 1`
-    else
-        # we are on the same subnet
-        _srcaddr=`echo $_netdev|awk '{print $5}'|head -n 1`
-        _netdev=`echo $_netdev|awk '{print $3}'|head -n 1`
-    fi
+    _srcaddr=$(get_ip_route_field "$_route" "src")
+    _netdev=$(get_ip_route_field "$_route" "dev")
 
     kdump_setup_netdev "${_netdev}" "${_srcaddr}"
 
@@ -504,10 +543,12 @@ kdump_setup_iscsi_device() {
     kdump_setup_netdev $netdev $srcaddr
 
     # prepare netroot= command line
-    # FIXME: IPV6 addresses require explicit [] around $tgt_ipaddr
     # 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
@@ -628,10 +669,28 @@ kdump_install_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
@@ -643,6 +702,7 @@ install() {
     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"
@@ -666,7 +726,8 @@ install() {
 installkernel() {
     wdt=$(lsmod|cut -f1 -d' '|grep "wdt$")
     if [ -n "$wdt" ]; then
-        [ "$wdt" = "iTCO_wdt" ] && instmods lpc_ich
+        [ "$wdt" = "iTCO_wdt" ] && instmods lpc_ich &&
+            echo "rd.driver.pre=lpc_ich,iTCO_wdt " >> ${initdir}/etc/cmdline.d/00-wdt.conf
         instmods $wdt
     fi
 }
diff --git a/SOURCES/kdump-lib-initramfs.sh b/SOURCES/kdump-lib-initramfs.sh
index 57b8304..68a94e8 100755
--- a/SOURCES/kdump-lib-initramfs.sh
+++ b/SOURCES/kdump-lib-initramfs.sh
@@ -7,7 +7,7 @@ CORE_COLLECTOR=""
 DEFAULT_CORE_COLLECTOR="makedumpfile -l --message-level 1 -d 31"
 DMESG_COLLECTOR="/sbin/vmcore-dmesg"
 DEFAULT_ACTION="reboot"
-DATEDIR=`date +%Y.%m.%d-%T`
+DATEDIR=`date +%Y-%m-%d-%T`
 HOST_IP='127.0.0.1'
 DUMP_INSTRUCTION=""
 SSH_KEY_LOCATION="/root/.ssh/kdump_id_rsa"
diff --git a/SOURCES/kdump-lib.sh b/SOURCES/kdump-lib.sh
index ef8417a..89dce8d 100755
--- a/SOURCES/kdump-lib.sh
+++ b/SOURCES/kdump-lib.sh
@@ -201,3 +201,32 @@ 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]"
+}
diff --git a/SOURCES/kdump.service b/SOURCES/kdump.service
index 24c1386..5144597 100644
--- a/SOURCES/kdump.service
+++ b/SOURCES/kdump.service
@@ -1,6 +1,7 @@
 [Unit]
 Description=Crash recovery kernel arming
-After=network.target network-online.target remote-fs.target
+After=network.target network-online.target remote-fs.target basic.target
+DefaultDependencies=no
 
 [Service]
 Type=oneshot
diff --git a/SOURCES/kdump.sysconfig.aarch64 b/SOURCES/kdump.sysconfig.aarch64
new file mode 100644
index 0000000..78b00bb
--- /dev/null
+++ b/SOURCES/kdump.sysconfig.aarch64
@@ -0,0 +1,28 @@
+# 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 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 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"
diff --git a/SOURCES/kdump.sysconfig.i386 b/SOURCES/kdump.sysconfig.i386
index 84b2447..bb7a6e5 100644
--- a/SOURCES/kdump.sysconfig.i386
+++ b/SOURCES/kdump.sysconfig.i386
@@ -16,7 +16,7 @@ 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 nr_cpus=1 reset_devices numa=off udev.children-max=2 panic=10 rootflags=nofail"
+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
diff --git a/SOURCES/kdump.sysconfig.ppc64 b/SOURCES/kdump.sysconfig.ppc64
index 5295626..dd09598 100644
--- a/SOURCES/kdump.sysconfig.ppc64
+++ b/SOURCES/kdump.sysconfig.ppc64
@@ -16,7 +16,7 @@ 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 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"
+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
diff --git a/SOURCES/kdump.sysconfig.ppc64le b/SOURCES/kdump.sysconfig.ppc64le
index 5295626..dd09598 100644
--- a/SOURCES/kdump.sysconfig.ppc64le
+++ b/SOURCES/kdump.sysconfig.ppc64le
@@ -16,7 +16,7 @@ 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 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"
+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
diff --git a/SOURCES/kdump.sysconfig.s390x b/SOURCES/kdump.sysconfig.s390x
index 745dd27..b103a88 100644
--- a/SOURCES/kdump.sysconfig.s390x
+++ b/SOURCES/kdump.sysconfig.s390x
@@ -16,7 +16,7 @@ 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="nr_cpus=1 cgroup_disable=memory numa=off udev.children-max=2 panic=10 rootflags=nofail"
+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=""
diff --git a/SOURCES/kdump.sysconfig.x86_64 b/SOURCES/kdump.sysconfig.x86_64
index d9ad9b5..7991d68 100644
--- a/SOURCES/kdump.sysconfig.x86_64
+++ b/SOURCES/kdump.sysconfig.x86_64
@@ -16,7 +16,7 @@ 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 nr_cpus=1 reset_devices cgroup_disable=memory mce=off numa=off udev.children-max=2 panic=10 rootflags=nofail acpi_no_memhotplug"
+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"
 
 # Any additional kexec arguments required.  In most situations, this should
 # be left empty
diff --git a/SOURCES/kdumpctl b/SOURCES/kdumpctl
index f1b72da..029ded9 100755
--- a/SOURCES/kdumpctl
+++ b/SOURCES/kdumpctl
@@ -105,7 +105,7 @@ prepare_cmdline()
 	else
 		cmdline=${KDUMP_COMMANDLINE}
 	fi
-	cmdline=`remove_cmdline_param "$cmdline" crashkernel hugepages hugepagesz`
+	cmdline=`remove_cmdline_param "$cmdline" crashkernel hugepages hugepagesz panic_on_warn`
 
 
 	cmdline="${cmdline} ${KDUMP_COMMANDLINE_APPEND}"
@@ -259,6 +259,8 @@ check_config()
 		esac
 	done < $KDUMP_CONFIG_FILE
 
+	check_default_config || return 1
+
 	check_fence_kdump_config || return 1
 
 	return 0
@@ -554,6 +556,14 @@ propagate_ssh_key()
 	fi
 }
 
+show_reserved_mem()
+{
+    local mem=$(cat /sys/kernel/kexec_crash_size)
+    local mem_mb=$(expr $mem / 1024 / 1024)
+
+    echo "Reserved "$mem_mb"MB memory for crash kernel"
+}
+
 is_fadump_capable()
 {
 	# Check if firmware-assisted dump is enabled
@@ -803,6 +813,25 @@ start_dump()
 	return $?
 }
 
+check_default_config()
+{
+	local default_option
+
+	default_option=$(awk '$1 ~ /^default$/ {print $2;}' $KDUMP_CONFIG_FILE)
+	if [ -z "$default_option" ]; then
+		return 0
+	else
+		case "$default_option" in
+		  reboot|halt|poweroff|shell|dump_to_rootfs)
+			return 0
+		  ;;
+		  *)
+			echo $"Usage kdump.conf: default {reboot|halt|poweroff|shell|dump_to_rootfs}"
+			return 1
+		esac
+	fi
+}
+
 start()
 {
 	check_config
@@ -946,8 +975,11 @@ main ()
 	  propagate)
 		propagate_ssh_key
 		;;
+	  showmem)
+		show_reserved_mem
+		;;
 	  *)
-		echo $"Usage: $0 {start|stop|status|restart|propagate}"
+		echo $"Usage: $0 {start|stop|status|restart|propagate|showmem}"
 		exit 1
 	esac
 }
diff --git a/SOURCES/kdumpctl.8 b/SOURCES/kdumpctl.8
new file mode 100644
index 0000000..023562b
--- /dev/null
+++ b/SOURCES/kdumpctl.8
@@ -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)
diff --git a/SOURCES/kexec-tools-2.0.7-makedumpfile-Support-ARM64.patch b/SOURCES/kexec-tools-2.0.7-makedumpfile-Support-ARM64.patch
new file mode 100644
index 0000000..f435c89
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.7-makedumpfile-Support-ARM64.patch
@@ -0,0 +1,371 @@
+From 145707b5b6495467515cb6f3e0814df81cb55404 Mon Sep 17 00:00:00 2001
+Message-Id: <145707b5b6495467515cb6f3e0814df81cb55404.1431708455.git.panand@redhat.com>
+From: Pratyush Anand <panand@redhat.com>
+Date: Tue, 28 Apr 2015 15:15:15 +0530
+Subject: [PATCH] makedumpfile: Support ARM64
+
+Patch adds support for ARM64 in makedumpfile. It takes care of vmalloc,
+vmemmap, module and directly map kernel memory region's translation.
+
+Signed-off-by: Pratyush Anand <panand@redhat.com>
+---
+ Makefile       |   1 +
+ arch/arm64.c   | 259 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ makedumpfile.h |  49 +++++++++++
+ 3 files changed, 309 insertions(+)
+ create mode 100644 arch/arm64.c
+
+diff --git a/makedumpfile-1.5.7/Makefile b/makedumpfile-1.5.7/Makefile
+index e45c3cfe5e9d..b8d77dbad856 100644
+--- a/makedumpfile-1.5.7/Makefile
++++ b/makedumpfile-1.5.7/Makefile
+@@ -49,6 +49,7 @@ SRC_BASE = makedumpfile.c makedumpfile.h diskdump_mod.h sadump_mod.h sadump_info
+ SRC_PART = print_info.c dwarf_info.c elf_info.c erase_info.c sadump_info.c cache.c
+ OBJ_PART=$(patsubst %.c,%.o,$(SRC_PART))
+ SRC_ARCH = arch/arm.c arch/x86.c arch/x86_64.c arch/ia64.c arch/ppc64.c arch/s390x.c arch/ppc.c
++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
+ OBJ_ARCH=$(patsubst %.c,%.o,$(SRC_ARCH))
+ 
+ LIBS = -ldw -lbz2 -lebl -ldl -lelf -lz
+diff --git a/makedumpfile-1.5.7/arch/arm64.c b/makedumpfile-1.5.7/arch/arm64.c
+new file mode 100644
+index 000000000000..28e2adef7ae3
+--- /dev/null
++++ b/makedumpfile-1.5.7/arch/arm64.c
+@@ -0,0 +1,259 @@
++/*
++ * arch/arm64.c : Based on arch/arm.c
++ *
++ * Copyright (C) 2015 Red Hat, Pratyush Anand <panand@redhat.com>
++ *
++ * 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 (version 2 of the License).
++ *
++ * 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.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#ifdef __aarch64__
++
++#include "../elf_info.h"
++#include "../makedumpfile.h"
++#include "../print_info.h"
++
++#if CONFIG_ARM64_PGTABLE_LEVELS == 2
++typedef struct {
++	unsigned long pgd;
++} pgd_t;
++
++typedef struct {
++	pgd_t pgd;
++} pud_t;
++
++typedef struct {
++	pud_t pud;
++} pmd_t;
++
++#define pud_offset(pgd, vaddr) 	((pud_t *)pgd)
++#define pmd_offset(pud, vaddr) 	((pmd_t *)pud)
++#define pgd_val(x)		((x).pgd)
++#define pud_val(x)		(pgd_val((x).pgd))
++#define pmd_val(x)		(pud_val((x).pud))
++
++#define PUD_SHIFT		PGDIR_SHIFT
++#define PUD_SIZE		(1UL << PUD_SHIFT)
++
++#endif
++
++typedef struct {
++	unsigned long pte;
++} pte_t;
++#define pte_val(x)		((x).pte)
++
++#define PAGE_SIZE		(1UL << PAGE_SHIFT)
++#define PAGE_MASK		(~(PAGE_SIZE - 1))
++#define PGDIR_SHIFT		((PAGE_SHIFT - 3) * ARM64_PGTABLE_LEVELS + 3)
++#define PTRS_PER_PGD		(1 << (VA_BITS - PGDIR_SHIFT))
++#define PMD_SHIFT		((PAGE_SHIFT - 3) * 2 + 3)
++#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - 3))
++#define PMD_SHIFT		((PAGE_SHIFT - 3) * 2 + 3)
++#define PMD_SIZE		(1UL << PMD_SHIFT)
++#define PMD_MASK		(~(PMD_SIZE - 1))
++#define PTRS_PER_PMD		PTRS_PER_PTE
++
++#define PAGE_PRESENT		(1 << 0)
++#define SECTIONS_SIZE_BITS	30
++/*
++
++* Highest possible physical address supported.
++*/
++#define PHYS_MASK_SHIFT		48
++#define PHYS_MASK		((1UL << PHYS_MASK_SHIFT) - 1)
++
++#define PMD_TYPE_MASK		3
++#define PMD_TYPE_SECT		1
++#define PMD_TYPE_TABLE		3
++
++#define __va(paddr) 			((paddr) - info->phys_base + PAGE_OFFSET)
++#define __pa(vaddr) 			((vaddr) - PAGE_OFFSET + info->phys_base)
++
++#define pgd_index(vaddr) 		(((vaddr) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
++#define pgd_offset(pgdir, vaddr)	((pgd_t *)(pgdir) + pgd_index(vaddr))
++
++#define pte_index(addr) 		(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
++#define pmd_page_vaddr(pmd)		(__va(pmd_val(pmd) & PHYS_MASK & (int32_t)PAGE_MASK))
++#define pte_offset(dir, vaddr) 		((pte_t*)pmd_page_vaddr((*dir)) + pte_index(vaddr))
++
++/* kernel struct page size can be kernel version dependent, currently
++ * keep it constant.
++ */
++#define KERN_STRUCT_PAGE_SIZE		64
++#define ALIGN(x, a) 			(((x) + (a) - 1) & ~((a) - 1))
++#define PFN_DOWN(x)			((x) >> PAGE_SHIFT)
++#define VMEMMAP_SIZE			ALIGN((1UL << (VA_BITS - PAGE_SHIFT)) * KERN_STRUCT_PAGE_SIZE, PUD_SIZE)
++#define MODULES_END			PAGE_OFFSET
++#define MODULES_VADDR			(MODULES_END - 0x4000000)
++
++int is_vmalloc_addr(unsigned long vaddr)
++{
++	return (vaddr >= VMALLOC_START && vaddr <= VMALLOC_END);
++}
++
++static int is_vtop_from_page_table_arm64(unsigned long vaddr)
++{
++	/* If virtual address lies in vmalloc, vmemmap or module space
++	 * region then, get the physical address from page table.
++	 */
++	return ((vaddr >= VMALLOC_START && vaddr <= VMALLOC_END)
++		|| (vaddr >= VMEMMAP_START && vaddr <= VMEMMAP_END)
++		|| (vaddr >= MODULES_VADDR && vaddr <= MODULES_END));
++}
++
++int get_phys_base_arm64(void)
++{
++	unsigned long phys_base = ULONG_MAX;
++	unsigned long long phys_start;
++	int i;
++	/*
++	 * We resolve phys_base from PT_LOAD segments. LMA contains physical
++	 * address of the segment, and we use the lowest start as
++	 * phys_base.
++	 */
++	for (i = 0; get_pt_load(i, &phys_start, NULL, NULL, NULL); i++) {
++		if (phys_start < phys_base)
++			phys_base = phys_start;
++	}
++
++	if (phys_base == ULONG_MAX) {
++		ERRMSG("Can't determine phys_base\n");
++		return FALSE;
++	}
++
++	info->phys_base = phys_base;
++
++	DEBUG_MSG("phys_base    : %lx\n", phys_base);
++
++	return TRUE;
++}
++
++int get_machdep_info_arm64(void)
++{
++	info->max_physmem_bits = PHYS_MASK_SHIFT;
++	info->section_size_bits = SECTIONS_SIZE_BITS;
++	info->page_offset = KVBASE;
++	info->vmalloc_start = 0xffffffffffffffffUL << VA_BITS;
++	info->vmalloc_end = PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - 0x10000;
++	info->vmemmap_start = VMALLOC_END + 0x10000;
++	info->vmemmap_end = VMEMMAP_START + VMEMMAP_SIZE;
++
++	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);
++	DEBUG_MSG("vmalloc_start    : %lx\n", info->vmalloc_start);
++	DEBUG_MSG("vmalloc_end      : %lx\n", info->vmalloc_end);
++	DEBUG_MSG("vmemmap_start    : %lx\n", info->vmemmap_start);
++	DEBUG_MSG("vmemmap_end      : %lx\n", info->vmemmap_end);
++	DEBUG_MSG("modules_start    : %lx\n", MODULES_VADDR);
++	DEBUG_MSG("modules_end      : %lx\n", MODULES_END);
++
++	return TRUE;
++}
++
++unsigned long long kvtop_xen_arm64(unsigned long kvaddr)
++{
++	return ERROR;
++}
++
++int get_xen_basic_info_arm64(void)
++{
++	return ERROR;
++}
++
++int get_xen_info_arm64(void)
++{
++	return ERROR;
++}
++
++int get_versiondep_info_arm64(void)
++{
++	return TRUE;
++}
++
++/*
++ * vtop_arm64() - translate arbitrary virtual address to physical
++ * @vaddr: virtual address to translate
++ *
++ * Function translates @vaddr into physical address using page tables. This
++ * address can be any virtual address. Returns physical address of the
++ * corresponding virtual address or %NOT_PADDR when there is no translation.
++ */
++static unsigned long long vtop_arm64(unsigned long vaddr)
++{
++	unsigned long long paddr = NOT_PADDR;
++	pgd_t	*pgda, pgdv;
++	pud_t	*puda;
++	pmd_t	*pmda, pmdv;
++	pte_t 	*ptea, ptev;
++
++	if (SYMBOL(swapper_pg_dir) == NOT_FOUND_SYMBOL) {
++		ERRMSG("Can't get the symbol of swapper_pg_dir.\n");
++		return NOT_PADDR;
++	}
++
++	pgda = pgd_offset(SYMBOL(swapper_pg_dir), vaddr);
++	if (!readmem(VADDR, (unsigned long long)pgda, &pgdv, sizeof(pgdv))) {
++		ERRMSG("Can't read pgd\n");
++		return NOT_PADDR;
++	}
++
++	puda = pud_offset(pgda, vaddr);
++	pmda = pmd_offset(puda, vaddr);
++	if (!readmem(VADDR, (unsigned long long)pmda, &pmdv, sizeof(pmdv))) {
++		ERRMSG("Can't read pmd\n");
++		return NOT_PADDR;
++	}
++
++	switch (pmd_val(pmdv) & PMD_TYPE_MASK) {
++	case PMD_TYPE_TABLE:
++		ptea = pte_offset(&pmdv, vaddr);
++		/* 64k page */
++		if (!readmem(VADDR, (unsigned long long)ptea, &ptev, sizeof(ptev))) {
++			ERRMSG("Can't read pte\n");
++			return NOT_PADDR;
++		}
++
++		if (!(pte_val(ptev) & PAGE_PRESENT)) {
++			ERRMSG("Can't get a valid pte.\n");
++			return NOT_PADDR;
++		} else {
++
++			paddr = (PAGEBASE(pte_val(ptev)) & PHYS_MASK)
++					+ (vaddr & (PAGESIZE() - 1));
++		}
++		break;
++	case PMD_TYPE_SECT:
++		/* 1GB section */
++		paddr = (pmd_val(pmdv) & PMD_MASK) + (vaddr & (PMD_SIZE - 1));
++		break;
++	}
++
++	return paddr;
++}
++
++unsigned long long vaddr_to_paddr_arm64(unsigned long vaddr)
++{
++	/*
++	 * use translation tables when a) user has explicitly requested us to
++	 * perform translation for a given address. b) virtual address lies in
++	 * vmalloc, vmemmap or modules memory region. Otherwise we assume that
++	 * the translation is done within the kernel direct mapped region.
++	 */
++	if ((info->vaddr_for_vtop == vaddr) ||
++			is_vtop_from_page_table_arm64(vaddr))
++		return vtop_arm64(vaddr);
++
++	return __pa(vaddr);
++}
++#endif
+diff --git a/makedumpfile-1.5.7/makedumpfile.h b/makedumpfile-1.5.7/makedumpfile.h
+index 96830b071f6e..2af3a8e72e0a 100644
+--- a/makedumpfile-1.5.7/makedumpfile.h
++++ b/makedumpfile-1.5.7/makedumpfile.h
+@@ -483,6 +483,33 @@ do { \
+ #define VMEMMAP_START		(info->vmemmap_start)
+ #define VMEMMAP_END		(info->vmemmap_end)
+ 
++#ifdef __aarch64__
++#define CONFIG_ARM64_PGTABLE_LEVELS	2
++#define CONFIG_ARM64_VA_BITS		42
++#define CONFIG_ARM64_64K_PAGES		1
++
++/* Currently we only suport following defines based on above
++ * config definitions.
++ * TODOs: We need to find a way to get above defines dynamically and
++ * then to support following definitions based on that
++ */
++
++#if CONFIG_ARM64_PGTABLE_LEVELS == 2
++#define ARM64_PGTABLE_LEVELS	2
++#endif
++
++#if CONFIG_ARM64_VA_BITS == 42
++#define VA_BITS			42
++#endif
++
++#ifdef CONFIG_ARM64_64K_PAGES
++#define PAGE_SHIFT		16
++#endif
++
++#define KVBASE_MASK		(0xffffffffffffffffUL << (VA_BITS - 1))
++#define KVBASE			(SYMBOL(_stext) & KVBASE_MASK)
++#endif /* aarch64 */
++
+ #ifdef __arm__
+ #define KVBASE_MASK		(0xffff)
+ #define KVBASE			(SYMBOL(_stext) & ~KVBASE_MASK)
+@@ -757,6 +784,23 @@ do { \
+ /*
+  * The function of dependence on machine
+  */
++#ifdef __aarch64__
++int get_phys_base_arm64(void);
++int get_machdep_info_arm64(void);
++unsigned long long vaddr_to_paddr_arm64(unsigned long vaddr);
++int get_versiondep_info_arm64(void);
++int get_xen_basic_info_arm64(void);
++int get_xen_info_arm64(void);
++int is_vmalloc_addr_arm64(unsigned long vaddr);
++#define vaddr_to_paddr(X)	vaddr_to_paddr_arm64(X)
++#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_xen_basic_info_arch(X) get_xen_basic_info_arm64(X)
++#define get_xen_info_arch(X) 	get_xen_info_arm64(X)
++#define is_vmalloc_addr(X)	is_vmalloc_addr_arm64(X)
++#endif /* aarch64 */
++
+ #ifdef __arm__
+ int get_phys_base_arm(void);
+ int get_machdep_info_arm(void);
+@@ -1581,6 +1625,11 @@ struct domain_list {
+ #define PAGES_PER_MAPWORD 	(sizeof(unsigned long) * 8)
+ #define MFNS_PER_FRAME		(info->page_size / sizeof(unsigned long))
+ 
++#ifdef __aarch64__
++unsigned long long kvtop_xen_arm64(unsigned long kvaddr);
++#define kvtop_xen(X)	kvtop_xen_arm64(X)
++#endif /* aarch64 */
++
+ #ifdef __arm__
+ #define kvtop_xen(X)	FALSE
+ #define get_xen_basic_info_arch(X) FALSE
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-Don-t-bail-out-if-check_cpu_nodes-fails.patch b/SOURCES/kexec-tools-2.0.8-Don-t-bail-out-if-check_cpu_nodes-fails.patch
new file mode 100644
index 0000000..383e08f
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-Don-t-bail-out-if-check_cpu_nodes-fails.patch
@@ -0,0 +1,34 @@
+From 224112c147c398df25c543fcea42b3a75635c417 Mon Sep 17 00:00:00 2001
+Message-Id: <224112c147c398df25c543fcea42b3a75635c417.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: Mark Salter <msalter@redhat.com>
+Date: Mon, 27 Apr 2015 11:18:25 -0400
+Subject: [PATCH 17/17] Don't bail out if check_cpu_nodes() fails
+
+Current check_cpu_nodes() will fail if firmware does not provide a
+devicetree with cpu nodes. When booting with ACPI, we cannot count
+on a devicetree with cpu nodes. For now, just warn on error rather
+than bailing out. This will allow kexec to work with moonshot.
+
+Signed-off-by: Mark Salter <msalter@redhat.com>
+---
+ kexec/arch/arm64/kexec-arm64.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+index d884c7c1707d..12c589f8001c 100644
+--- a/kexec/arch/arm64/kexec-arm64.c
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -639,7 +639,7 @@ int arm64_load_other_segments(struct kexec_info *info,
+ 	result =  check_cpu_nodes(&dtb_1, &dtb_2);
+ 
+ 	if (result)
+-		return result;
++		fprintf(stderr, "kexec: Warning: No device tree available.\n");
+ 
+ 	/*
+ 	 * Put the DTB after the kernel with an alignment of 128 KiB, giving
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-add-aarch64-to-configure.patch b/SOURCES/kexec-tools-2.0.8-add-aarch64-to-configure.patch
new file mode 100644
index 0000000..6db6dad
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-add-aarch64-to-configure.patch
@@ -0,0 +1,13 @@
+diff -Nur -x '*autom4te.cache*' kexec-tools-2.0.7.orig/configure kexec-tools-2.0.7/configure
+--- kexec-tools-2.0.7.orig/configure	2014-06-08 20:51:35.000000000 -0400
++++ kexec-tools-2.0.7/configure	2015-04-21 13:58:57.272137413 -0400
+@@ -2195,6 +2195,9 @@
+ 		ARCH="ppc64"
+ 		SUBARCH="LE"
+ 		;;
++	aarch64* )
++		ARCH="arm64"
++		;;
+ 	arm* )
+ 		ARCH="arm"
+ 		;;
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-Add-arm64-kexec-support.patch b/SOURCES/kexec-tools-2.0.8-arm64-Add-arm64-kexec-support.patch
new file mode 100644
index 0000000..f1d89c9
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-Add-arm64-kexec-support.patch
@@ -0,0 +1,1772 @@
+From 21014aa0868f11223e3b33afa1b6320b79187dbc Mon Sep 17 00:00:00 2001
+Message-Id: <21014aa0868f11223e3b33afa1b6320b79187dbc.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: Geoff Levand <geoff@infradead.org>
+Date: Fri, 17 Apr 2015 10:54:55 -0700
+Subject: [PATCH 02/17] arm64: Add arm64 kexec support
+
+Add kexec reboot support for ARM64 platforms.  Uses purgatory.
+
+Signed-off-by: Geoff Levand <geoff@infradead.org>
+---
+ configure.ac                            |    3 +
+ kexec/Makefile                          |    1 +
+ kexec/arch/arm64/Makefile               |   40 ++
+ kexec/arch/arm64/crashdump-arm64.c      |   21 +
+ kexec/arch/arm64/crashdump-arm64.h      |   12 +
+ kexec/arch/arm64/image-header.h         |   95 +++
+ kexec/arch/arm64/include/arch/options.h |   44 ++
+ kexec/arch/arm64/kexec-arm64.c          | 1041 +++++++++++++++++++++++++++++++
+ kexec/arch/arm64/kexec-arm64.h          |   51 ++
+ kexec/arch/arm64/kexec-elf-arm64.c      |  123 ++++
+ kexec/arch/arm64/kexec-image-arm64.c    |   50 ++
+ kexec/kexec-syscall.h                   |    9 +-
+ purgatory/Makefile                      |    1 +
+ purgatory/arch/arm64/Makefile           |   18 +
+ purgatory/arch/arm64/entry.S            |   54 ++
+ purgatory/arch/arm64/purgatory-arm64.c  |   35 ++
+ 16 files changed, 1596 insertions(+), 2 deletions(-)
+ create mode 100644 kexec/arch/arm64/Makefile
+ create mode 100644 kexec/arch/arm64/crashdump-arm64.c
+ create mode 100644 kexec/arch/arm64/crashdump-arm64.h
+ create mode 100644 kexec/arch/arm64/image-header.h
+ create mode 100644 kexec/arch/arm64/include/arch/options.h
+ create mode 100644 kexec/arch/arm64/kexec-arm64.c
+ create mode 100644 kexec/arch/arm64/kexec-arm64.h
+ create mode 100644 kexec/arch/arm64/kexec-elf-arm64.c
+ create mode 100644 kexec/arch/arm64/kexec-image-arm64.c
+ create mode 100644 purgatory/arch/arm64/Makefile
+ create mode 100644 purgatory/arch/arm64/entry.S
+ create mode 100644 purgatory/arch/arm64/purgatory-arm64.c
+
+diff --git a/configure.ac b/configure.ac
+index 6946780d498f..701ed69c5033 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -35,6 +35,9 @@ case $target_cpu in
+ 		ARCH="ppc64"
+ 		SUBARCH="LE"
+ 		;;
++	aarch64* )
++		ARCH="arm64"
++		;;
+ 	arm* )
+ 		ARCH="arm"
+ 		;;
+diff --git a/kexec/Makefile b/kexec/Makefile
+index 6937a4dbb38b..fac668072463 100644
+--- a/kexec/Makefile
++++ b/kexec/Makefile
+@@ -75,6 +75,7 @@ KEXEC_SRCS			+= $($(ARCH)_DT_OPS)
+ 
+ include $(srcdir)/kexec/arch/alpha/Makefile
+ include $(srcdir)/kexec/arch/arm/Makefile
++include $(srcdir)/kexec/arch/arm64/Makefile
+ include $(srcdir)/kexec/arch/i386/Makefile
+ include $(srcdir)/kexec/arch/ia64/Makefile
+ include $(srcdir)/kexec/arch/m68k/Makefile
+diff --git a/kexec/arch/arm64/Makefile b/kexec/arch/arm64/Makefile
+new file mode 100644
+index 000000000000..37414dc5c900
+--- /dev/null
++++ b/kexec/arch/arm64/Makefile
+@@ -0,0 +1,40 @@
++
++arm64_FS2DT += kexec/fs2dt.c
++arm64_FS2DT_INCLUDE += -include $(srcdir)/kexec/arch/arm64/kexec-arm64.h \
++	-include $(srcdir)/kexec/arch/arm64/crashdump-arm64.h
++
++arm64_DT_OPS += kexec/dt-ops.c
++
++arm64_CPPFLAGS += -I $(srcdir)/kexec/
++
++arm64_KEXEC_SRCS += \
++	kexec/arch/arm64/kexec-arm64.c \
++	kexec/arch/arm64/kexec-image-arm64.c \
++	kexec/arch/arm64/kexec-elf-arm64.c \
++	kexec/arch/arm64/crashdump-arm64.c
++
++arm64_ARCH_REUSE_INITRD =
++arm64_ADD_SEGMENT =
++arm64_VIRT_TO_PHYS =
++arm64_PHYS_TO_VIRT =
++
++dist += $(arm64_KEXEC_SRCS) \
++	kexec/arch/arm64/Makefile \
++	kexec/arch/arm64/kexec-arm64.h \
++	kexec/arch/arm64/crashdump-arm64.h
++
++ifdef HAVE_LIBFDT
++
++LIBS += -lfdt
++
++else
++
++include $(srcdir)/kexec/libfdt/Makefile.libfdt
++
++libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%)
++
++arm64_CPPFLAGS += -I$(srcdir)/kexec/libfdt
++
++arm64_KEXEC_SRCS += $(libfdt_SRCS)
++
++endif
+diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
+new file mode 100644
+index 000000000000..d2272c8124d0
+--- /dev/null
++++ b/kexec/arch/arm64/crashdump-arm64.c
+@@ -0,0 +1,21 @@
++/*
++ * ARM64 crashdump.
++ */
++
++#define _GNU_SOURCE
++
++#include <errno.h>
++#include <linux/elf.h>
++
++#include "kexec.h"
++#include "crashdump.h"
++#include "crashdump-arm64.h"
++#include "kexec-arm64.h"
++#include "kexec-elf.h"
++
++struct memory_ranges usablemem_rgns = {};
++
++int is_crashkernel_mem_reserved(void)
++{
++	return 0;
++}
+diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
+new file mode 100644
+index 000000000000..f33c7a25b454
+--- /dev/null
++++ b/kexec/arch/arm64/crashdump-arm64.h
+@@ -0,0 +1,12 @@
++/*
++ * ARM64 crashdump.
++ */
++
++#if !defined(CRASHDUMP_ARM64_H)
++#define CRASHDUMP_ARM64_H
++
++#include "kexec.h"
++
++extern struct memory_ranges usablemem_rgns;
++
++#endif
+diff --git a/kexec/arch/arm64/image-header.h b/kexec/arch/arm64/image-header.h
+new file mode 100644
+index 000000000000..acb839ab889c
+--- /dev/null
++++ b/kexec/arch/arm64/image-header.h
+@@ -0,0 +1,95 @@
++/*
++ * ARM64 binary image support.
++ * Copyright (C) 2014 Linaro.
++ */
++
++#if !defined(__ARM64_IMAGE_HEADER_H)
++#define __ARM64_IMAGE_HEADER_H
++
++#if !defined(__KERNEL__)
++#include <stdint.h>
++#endif
++
++#if !defined(__ASSEMBLY__)
++
++/**
++ * struct arm64_image_header - arm64 kernel image header.
++ *
++ * @pe_sig: Optional PE format 'MZ' signature.
++ * @branch_code: Reserved for instructions to branch to stext.
++ * @text_offset: The image load offset in LSB byte order.
++ * @image_size: An estimated size of the memory image size in LSB byte order.
++ * @flags: Bit flags:
++ *  Bit 7.0: Image byte order, 1=MSB.
++ * @reserved_1: Reserved.
++ * @magic: Magic number, "ARM\x64".
++ * @pe_header: Optional offset to a PE format header.
++ **/
++
++struct arm64_image_header {
++	uint8_t pe_sig[2];
++	uint16_t branch_code[3];
++	uint64_t text_offset;
++	uint64_t image_size;
++	uint8_t flags[8];
++	uint64_t reserved_1[3];
++	uint8_t magic[4];
++	uint32_t pe_header;
++};
++
++static const uint8_t arm64_image_magic[4] = {'A', 'R', 'M', 0x64U};
++static const uint8_t arm64_image_pe_sig[2] = {'M', 'Z'};
++static const uint64_t arm64_image_flag_7_be = 0x01U;
++
++/**
++ * arm64_header_check_magic - Helper to check the arm64 image header.
++ *
++ * Returns non-zero if header is OK.
++ */
++
++static inline int arm64_header_check_magic(const struct arm64_image_header *h)
++{
++	if (!h)
++		return 0;
++
++	if (!h->text_offset)
++		return 0;
++
++	return (h->magic[0] == arm64_image_magic[0]
++		&& h->magic[1] == arm64_image_magic[1]
++		&& h->magic[2] == arm64_image_magic[2]
++		&& h->magic[3] == arm64_image_magic[3]);
++}
++
++/**
++ * arm64_header_check_pe_sig - Helper to check the arm64 image header.
++ *
++ * Returns non-zero if 'MZ' signature is found.
++ */
++
++static inline int arm64_header_check_pe_sig(const struct arm64_image_header *h)
++{
++	if (!h)
++		return 0;
++
++	return (h->pe_sig[0] == arm64_image_pe_sig[0]
++		&& h->pe_sig[1] == arm64_image_pe_sig[1]);
++}
++
++/**
++ * arm64_header_check_msb - Helper to check the arm64 image header.
++ *
++ * Returns non-zero if the image was built as big endian.
++ */
++
++static inline int arm64_header_check_msb(const struct arm64_image_header *h)
++{
++	if (!h)
++		return 0;
++
++	return !!(h->flags[7] & arm64_image_flag_7_be);
++}
++
++#endif /* !defined(__ASSEMBLY__) */
++
++#endif
+diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h
+new file mode 100644
+index 000000000000..51afc5f1f6f2
+--- /dev/null
++++ b/kexec/arch/arm64/include/arch/options.h
+@@ -0,0 +1,44 @@
++#if !defined(KEXEC_ARCH_ARM64_OPTIONS_H)
++#define KEXEC_ARCH_ARM64_OPTIONS_H
++
++#define OPT_APPEND	((OPT_MAX)+0)
++#define OPT_DTB		((OPT_MAX)+1)
++#define OPT_INITRD	((OPT_MAX)+2)
++#define OPT_LITE	((OPT_MAX)+3)
++#define OPT_PORT	((OPT_MAX)+4)
++#define OPT_ARCH_MAX	((OPT_MAX)+5)
++
++#define KEXEC_ARCH_OPTIONS \
++	KEXEC_OPTIONS \
++	{ "append",       1, NULL, OPT_APPEND }, \
++	{ "command-line", 1, NULL, OPT_APPEND }, \
++	{ "dtb",          1, NULL, OPT_DTB }, \
++	{ "initrd",       1, NULL, OPT_INITRD }, \
++	{ "lite",         0, NULL, OPT_LITE }, \
++	{ "port",         1, NULL, OPT_PORT }, \
++	{ "ramdisk",      1, NULL, OPT_INITRD }, \
++
++#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */
++#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS
++#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR
++
++static const char arm64_opts_usage[] __attribute__ ((unused)) =
++"     --append=STRING       Set the kernel command line to STRING.\n"
++"     --command-line=STRING Set the kernel command line to STRING.\n"
++"     --dtb=FILE            Use FILE as the device tree blob.\n"
++"     --initrd=FILE         Use FILE as the kernel initial ramdisk.\n"
++"     --lite                Fast reboot, no memory integrity checks - currently NOT SUPPORTED.\n");
++"     --port=ADDRESS        Purgatory output to port ADDRESS.\n"
++"     --ramdisk=FILE        Use FILE as the kernel initial ramdisk.\n";
++
++struct arm64_opts {
++	const char *command_line;
++	const char *dtb;
++	const char *initrd;
++	uint64_t port;
++	int lite;
++};
++
++extern struct arm64_opts arm64_opts;
++
++#endif
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+new file mode 100644
+index 000000000000..0860810b6e86
+--- /dev/null
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -0,0 +1,1041 @@
++/*
++ * ARM64 kexec.
++ */
++
++#define _GNU_SOURCE
++
++#include <assert.h>
++#include <ctype.h>
++#include <dirent.h>
++#include <errno.h>
++#include <getopt.h>
++#include <inttypes.h>
++#include <libfdt.h>
++#include <limits.h>
++#include <stdio.h>
++#include <stddef.h>
++#include <stdlib.h>
++#include <string.h>
++
++#include <sys/stat.h>
++
++#include <linux/elf.h>
++
++#include "dt-ops.h"
++#include "kexec.h"
++#include "crashdump.h"
++#include "crashdump-arm64.h"
++#include "kexec-arm64.h"
++#include "fs2dt.h"
++#include "kexec-syscall.h"
++#include "arch/options.h"
++
++/* Global varables the core kexec routines expect. */
++
++unsigned char reuse_initrd;
++
++off_t initrd_base;
++off_t initrd_size;
++
++const struct arch_map_entry arches[] = {
++	{ "aarch64", KEXEC_ARCH_ARM64 },
++	{ "aarch64_be", KEXEC_ARCH_ARM64 },
++	{ NULL, 0 },
++};
++
++/* arm64 global varables. */
++
++struct arm64_opts arm64_opts;
++struct arm64_mem arm64_mem = {
++	.memstart = UINT64_MAX,
++};
++
++static void set_memstart(uint64_t v)
++{
++	if (arm64_mem.memstart == UINT64_MAX || v < arm64_mem.memstart)
++		arm64_mem.memstart = v;
++}
++
++static int check_memstart(void)
++{
++	return arm64_mem.memstart != UINT64_MAX;
++}
++
++void arch_usage(void)
++{
++	dbgprintf("Build time: %s : %s\n", __DATE__, __TIME__);
++	printf(arm64_opts_usage);
++}
++
++int arch_process_options(int argc, char **argv)
++{
++	static const char short_options[] = KEXEC_OPT_STR "";
++	static const struct option options[] = {
++		KEXEC_ARCH_OPTIONS
++		{ 0 }
++	};
++	int opt;
++
++	for (opt = 0; opt != -1; ) {
++		opt = getopt_long(argc, argv, short_options, options, 0);
++
++		switch (opt) {
++		case OPT_APPEND:
++			arm64_opts.command_line = optarg;
++			break;
++		case OPT_DTB:
++			arm64_opts.dtb = optarg;
++			break;
++		case OPT_INITRD:
++			arm64_opts.initrd = optarg;
++			break;
++		case OPT_LITE:
++			arm64_opts.lite = 1;
++			fprintf(stderr, "kexec: --lite option currently NOT SUPPORTED.\n");
++			break;
++		case OPT_PORT:
++			arm64_opts.port = strtoull(optarg, NULL, 0);
++			break;
++		default:
++			break; /* Ignore core and unknown options. */
++		}
++	}
++
++	kexec_debug = 1; // FIXME: for debugging only.
++
++	dbgprintf("%s:%d: command_line: %s\n", __func__, __LINE__,
++		arm64_opts.command_line);
++	dbgprintf("%s:%d: initrd: %s\n", __func__, __LINE__,
++		arm64_opts.initrd);
++	dbgprintf("%s:%d: dtb: %s\n", __func__, __LINE__, arm64_opts.dtb);
++	dbgprintf("%s:%d: lite: %d\n", __func__, __LINE__, arm64_opts.lite);
++	dbgprintf("%s:%d: port: 0x%" PRIx64 "\n", __func__, __LINE__,
++		arm64_opts.port);
++
++	return 0;
++}
++
++struct dtb {
++	char *buf;
++	off_t size;
++	const char *name;
++	const char *path;
++};
++
++static void dump_reservemap(const struct dtb *dtb)
++{
++	int i;
++
++	for (i = 0; ; i++) {
++		uint64_t address;
++		uint64_t size;
++
++		fdt_get_mem_rsv(dtb->buf, i, &address, &size);
++
++		if (!size)
++			break;
++
++		dbgprintf("%s: %s {%" PRIx64 ", %" PRIx64 "}\n", __func__,
++			dtb->name, address, size);
++	}
++}
++
++enum cpu_enable_method {
++	cpu_enable_method_unknown,
++	cpu_enable_method_psci,
++	cpu_enable_method_spin_table,
++};
++
++/**
++ * struct cpu_properties - Various properties from a device tree cpu node.
++ *
++ * These properties will be valid over a dtb re-size.
++ */
++
++struct cpu_properties {
++	uint64_t hwid;
++	uint64_t cpu_release_addr;
++	char node_path[128];
++	char enable_method[128];
++	enum cpu_enable_method type;
++};
++
++/**
++ * read_cpu_properties - Helper to read the device tree cpu properties.
++ */
++
++static int read_cpu_properties(struct cpu_properties *cp,
++	const struct dtb *dtb, int node_offset, unsigned int address_cells)
++{
++	int result;
++	const void *data;
++
++	result = fdt_get_path(dtb->buf, node_offset, cp->node_path,
++		sizeof(cp->node_path));
++
++	if (result < 0) {
++		fprintf(stderr, "kexec: %s:%d: %s: fdt_get_path failed: %s\n",
++			__func__, __LINE__, dtb->name, fdt_strerror(result));
++		return result;
++	}
++
++	data = fdt_getprop(dtb->buf, node_offset, "device_type", &result);
++
++	if (!data) {
++		dbgprintf("%s: %s (%s) read device_type failed: %s\n",
++			__func__, dtb->name, cp->node_path,
++			fdt_strerror(result));
++		return result == -FDT_ERR_NOTFOUND ? 0 : result;
++	}
++
++	if (strcmp(data, "cpu")) {
++		dbgprintf("%s: %s (%s): '%s'\n", __func__, dtb->name,
++			cp->node_path, (const char *)data);
++		return 0;
++	}
++
++	data = fdt_getprop(dtb->buf, node_offset, "reg", &result);
++
++	if (!data) {
++		fprintf(stderr, "kexec: %s:%d: read hwid failed: %s\n",
++			__func__, __LINE__, fdt_strerror(result));
++		return result;
++	}
++
++	cp->hwid = (address_cells == 1) ? fdt32_to_cpu(*(uint32_t *)data) :
++		fdt64_to_cpu(*(uint64_t *)data);
++
++	data = fdt_getprop(dtb->buf, node_offset, "enable-method", &result);
++
++	if (!data) {
++		fprintf(stderr,
++			"kexec: %s:%d: read enable_method failed: %s\n",
++			__func__, __LINE__, fdt_strerror(result));
++		return result;
++	}
++
++	strncpy(cp->enable_method, data, sizeof(cp->enable_method));
++	cp->enable_method[sizeof(cp->enable_method) - 1] = 0;
++
++	if (!strcmp(cp->enable_method, "psci")) {
++		cp->type = cpu_enable_method_psci;
++		return 1;
++	}
++
++	if (strcmp(cp->enable_method, "spin-table")) {
++		cp->type = cpu_enable_method_unknown;
++		return -1;
++	}
++
++	cp->type = cpu_enable_method_spin_table;
++
++	data = fdt_getprop(dtb->buf, node_offset, "cpu-release-addr", &result);
++
++	if (!data) {
++		fprintf(stderr, "kexec: %s:%d: "
++			"read cpu-release-addr failed: %s\n",
++			__func__, __LINE__, fdt_strerror(result));
++		return result;
++	}
++
++	cp->cpu_release_addr = fdt64_to_cpu(*(uint64_t *)data);
++
++	return 1;
++}
++
++static int check_cpu_properties(const struct cpu_properties *cp_1,
++	const struct cpu_properties *cp_2)
++{
++	assert(cp_1->hwid == cp_2->hwid);
++
++	if (cp_1->type != cp_2->type) {
++		fprintf(stderr,
++			"%s:%d: hwid-%" PRIx64 ": "
++			"Error: Different enable methods: %s -> %s\n",
++			__func__, __LINE__, cp_1->hwid, cp_1->enable_method,
++			cp_2->enable_method);
++		return -EINVAL;
++	}
++
++	if (cp_1->type != cpu_enable_method_psci
++		&& cp_1->type != cpu_enable_method_spin_table) {
++		fprintf(stderr,
++			"%s:%d: hwid-%" PRIx64 ": "
++			"Warning: Unknown enable method: %s.\n",
++			__func__, __LINE__, cp_1->hwid,
++			cp_1->enable_method);
++	}
++
++	if (cp_1->type == cpu_enable_method_spin_table) {
++		if (cp_1->cpu_release_addr != cp_2->cpu_release_addr) {
++			fprintf(stderr, "%s:%d: hwid-%" PRIx64 ": "
++				"Error: Different cpu-release-addr: "
++				"%" PRIx64 " -> %" PRIx64 ".\n",
++				__func__, __LINE__,
++				cp_1->hwid,
++				cp_2->cpu_release_addr,
++				cp_1->cpu_release_addr);
++			return -EINVAL;
++		}
++	}
++
++	dbgprintf("%s: hwid-%" PRIx64 ": OK\n", __func__, cp_1->hwid);
++
++	return 0;
++}
++
++struct cpu_info {
++	unsigned int cpu_count;
++	struct cpu_properties *cp;
++};
++
++static int read_cpu_info(struct cpu_info *info, const struct dtb *dtb)
++{
++	int i;
++	int offset;
++	int result;
++	int depth;
++	const void *data;
++	unsigned int address_cells;
++
++	offset = fdt_subnode_offset(dtb->buf, 0, "cpus");
++
++	if (offset < 0) {
++		fprintf(stderr, "kexec: %s:%d: read cpus node failed: %s\n",
++			__func__, __LINE__, fdt_strerror(offset));
++		return offset;
++	}
++
++	data = fdt_getprop(dtb->buf, offset, "#address-cells", &result);
++
++	if (!data) {
++		fprintf(stderr,
++			"kexec: %s:%d: read cpus address-cells failed: %s\n",
++			__func__, __LINE__, fdt_strerror(result));
++		return result;
++	}
++
++	address_cells = fdt32_to_cpu(*(uint32_t *)data);
++
++	if (address_cells < 1 || address_cells > 2) {
++		fprintf(stderr,
++			"kexec: %s:%d: bad cpus address-cells value: %u\n",
++			__func__, __LINE__, address_cells);
++		return -EINVAL;
++	}
++
++	for (i = 0, depth = 0; ; i++) {
++		info->cp = realloc(info->cp, (i + 1) * sizeof(*info->cp));
++
++		if (!info->cp) {
++			fprintf(stderr, "kexec: %s:%d: malloc failed: %s\n",
++				__func__, __LINE__, fdt_strerror(offset));
++			result = -ENOMEM;
++			goto on_error;
++		}
++
++next_node:
++		memset(&info->cp[i], 0, sizeof(*info->cp));
++
++		offset = fdt_next_node(dtb->buf, offset, &depth);
++
++		if (offset < 0) {
++			fprintf(stderr, "kexec: %s:%d: "
++				"read cpu node failed: %s\n", __func__,
++				__LINE__, fdt_strerror(offset));
++			result = offset;
++			goto on_error;
++		}
++
++		if (depth != 1)
++			break;
++
++		result = read_cpu_properties(&info->cp[i], dtb, offset,
++			address_cells);
++
++		if (result == 0)
++			goto next_node;
++
++		if (result < 0)
++			goto on_error;
++
++		if (info->cp[i].type == cpu_enable_method_psci)
++			dbgprintf("%s: %s cpu-%d (%s): hwid-%" PRIx64 ", '%s'\n",
++				__func__, dtb->name, i, info->cp[i].node_path,
++				info->cp[i].hwid,
++				info->cp[i].enable_method);
++		else
++			dbgprintf("%s: %s cpu-%d (%s): hwid-%" PRIx64 ", '%s', "
++				"cpu-release-addr %" PRIx64 "\n",
++				__func__, dtb->name, i, info->cp[i].node_path,
++				info->cp[i].hwid,
++				info->cp[i].enable_method,
++				info->cp[i].cpu_release_addr);
++	}
++
++	info->cpu_count = i;
++	return 0;
++
++on_error:
++	free(info->cp);
++	info->cp = NULL;
++	return result;
++}
++
++static int check_cpu_nodes(const struct dtb *dtb_1, const struct dtb *dtb_2)
++{
++	int result;
++	unsigned int cpu_1;
++	struct cpu_info info_1;
++	struct cpu_info info_2;
++	unsigned int to_process;
++
++	memset(&info_1, 0, sizeof(info_1));
++	memset(&info_2, 0, sizeof(info_2));
++
++	result = read_cpu_info(&info_1, dtb_1);
++
++	if (result)
++		goto on_exit;
++
++	result = read_cpu_info(&info_2, dtb_2);
++
++	if (result)
++		goto on_exit;
++
++	to_process = info_1.cpu_count < info_2.cpu_count
++		? info_1.cpu_count : info_2.cpu_count;
++
++	for (cpu_1 = 0; cpu_1 < info_1.cpu_count; cpu_1++) {
++		struct cpu_properties *cp_1 = &info_1.cp[cpu_1];
++		unsigned int cpu_2;
++
++		for (cpu_2 = 0; cpu_2 < info_2.cpu_count; cpu_2++) {
++			struct cpu_properties *cp_2 = &info_2.cp[cpu_2];
++
++			if (cp_1->hwid != cp_2->hwid)
++				continue;
++
++			to_process--;
++
++			result = check_cpu_properties(cp_1, cp_2);
++
++			if (result)
++				goto on_exit;
++		}
++	}
++
++	if (to_process) {
++		fprintf(stderr, "kexec: %s:%d: Warning: "
++			"Failed to process %u CPUs.\n",
++			__func__, __LINE__, to_process);
++		result = -EINVAL;
++		goto on_exit;
++	}
++
++on_exit:
++	free(info_1.cp);
++	free(info_2.cp);
++	return result;
++}
++
++static int set_bootargs(struct dtb *dtb, const char *command_line)
++{
++	int result;
++
++	if (!command_line || !command_line[0])
++		return 0;
++
++	result = dtb_set_bootargs((char **)&dtb->buf, &dtb->size, command_line);
++
++	if (result)
++		fprintf(stderr,
++			"kexec: Set device tree bootargs failed.\n");
++
++	return result;
++}
++
++static int read_proc_dtb(struct dtb *dtb, const char *command_line)
++{
++	int result;
++	struct stat s;
++	static const char path[] = "/proc/device-tree";
++
++	result = stat(path, &s);
++
++	if (result) {
++		dbgprintf("%s: %s\n", __func__, strerror(errno));
++		return -1;
++	}
++
++	dtb->path = path;
++	create_flatten_tree((char **)&dtb->buf, &dtb->size,
++		(command_line && command_line[0]) ? command_line : NULL);
++
++	return 0;
++}
++
++static int read_sys_dtb(struct dtb *dtb, const char *command_line)
++{
++	int result;
++	struct stat s;
++	static const char path[] = "/sys/firmware/fdt";
++
++	result = stat(path, &s);
++
++	if (result) {
++		dbgprintf("%s: %s\n", __func__, strerror(errno));
++		return -1;
++	}
++
++	dtb->path = path;
++	dtb->buf = slurp_file("/sys/firmware/fdt", &dtb->size);
++
++	return set_bootargs(dtb, command_line);
++}
++
++static int read_1st_dtb(struct dtb *dtb, const char *command_line)
++{
++	int result;
++
++	result = read_sys_dtb(dtb, command_line);
++
++	if (!result)
++		goto on_success;
++
++	result = read_proc_dtb(dtb, command_line);
++
++	if (!result)
++		goto on_success;
++
++	return -1;
++
++on_success:
++	dbgprintf("%s: found %s\n", __func__, dtb->path);
++	return 0;
++}
++
++static int setup_2nd_dtb(char *command_line, const struct dtb *dtb_1,
++	struct dtb *dtb_2)
++{
++	int result;
++
++	result = fdt_check_header(dtb_2->buf);
++
++	if (result) {
++		fprintf(stderr, "kexec: Invalid 2nd device tree.\n");
++		return -EINVAL;
++	}
++
++	result = set_bootargs(dtb_2, command_line);
++
++	dump_reservemap(dtb_2);
++
++	return result;
++}
++
++static uint64_t read_sink(const char *command_line)
++{
++	uint64_t v;
++	const char *p;
++
++	if (arm64_opts.port)
++		return arm64_opts.port;
++
++#if defined(ARM64_DEBUG_PORT)
++	return (uint64_t)(ARM64_DEBUG_PORT);
++#endif
++	if (!command_line)
++		return 0;
++
++	p = strstr(command_line, "earlyprintk=");
++
++	if (!p)
++		return 0;
++
++	while (*p != ',')
++		p++;
++
++	p++;
++
++	while (isspace(*p))
++		p++;
++
++	if (*p == 0)
++		return 0;
++
++	errno = 0;
++
++	v = strtoull(p, NULL, 0);
++
++	if (errno)
++		return 0;
++
++	return v;
++}
++
++/**
++ * arm64_load_other_segments - Prepare the dtb, initrd and purgatory segments.
++ */
++
++int arm64_load_other_segments(struct kexec_info *info,
++	unsigned long kernel_entry)
++{
++	int result;
++	struct mem_ehdr ehdr;
++	unsigned long dtb_max;
++	unsigned long dtb_base;
++	char *initrd_buf = NULL;
++	uint64_t purgatory_sink;
++	unsigned long purgatory_base;
++	struct dtb dtb_1 = {.name = "dtb_1"};
++	struct dtb dtb_2 = {.name = "dtb_2"};
++	char command_line[COMMAND_LINE_SIZE] = "";
++
++	if (arm64_opts.command_line) {
++		strncpy(command_line, arm64_opts.command_line,
++			sizeof(command_line));
++		command_line[sizeof(command_line) - 1] = 0;
++	}
++
++	purgatory_sink = read_sink(command_line);
++
++	dbgprintf("%s:%d: purgatory sink: 0x%" PRIx64 "\n", __func__, __LINE__,
++		purgatory_sink);
++
++	if (arm64_opts.dtb) {
++		dtb_2.buf = slurp_file(arm64_opts.dtb, &dtb_2.size);
++		assert(dtb_2.buf);
++	}
++
++	result = read_1st_dtb(&dtb_1, command_line);
++
++	if (result && !arm64_opts.dtb) {
++		fprintf(stderr, "kexec: Error: No device tree available.\n");
++		return result;
++	}
++
++	if (result && arm64_opts.dtb)
++		dtb_1 = dtb_2;
++	else if (!result && !arm64_opts.dtb)
++		dtb_2 = dtb_1;
++
++	result = setup_2nd_dtb(command_line, &dtb_1, &dtb_2);
++
++	if (result)
++		return result;
++	
++	result =  check_cpu_nodes(&dtb_1, &dtb_2);
++
++	if (result)
++		return result;
++
++	/*
++	 * Put the DTB after the kernel with an alignment of 128 KiB, giving
++	 * a max supported DTB size of 128 KiB (worst case).  Also add 2 KiB
++	 * to the DTB size for any DTB growth.
++	 */
++
++	dtb_max = dtb_2.size + 2 * 1024;
++
++	dtb_base = locate_hole(info, dtb_max, 128UL * 1024,
++		arm64_mem.memstart + arm64_mem.text_offset
++			+ arm64_mem.image_size,
++		_ALIGN_UP(arm64_mem.memstart + arm64_mem.text_offset,
++			512UL * 1024 * 1024),
++		1);
++
++	dbgprintf("dtb:    base %lx, size %lxh (%ld)\n", dtb_base, dtb_2.size,
++		dtb_2.size);
++
++	if (dtb_base == ULONG_MAX)
++		return -ENOMEM;
++
++	purgatory_base = dtb_base + dtb_2.size;
++	initrd_base = 0;
++	initrd_size = 0;
++
++	if (arm64_opts.initrd) {
++		initrd_buf = slurp_file(arm64_opts.initrd, &initrd_size);
++
++		if (!initrd_buf)
++			fprintf(stderr, "kexec: Empty ramdisk file.\n");
++		else {
++			/* Put the initrd after the DTB with an alignment of
++			 * page size. */
++
++			initrd_base = locate_hole(info, initrd_size, 0,
++				dtb_base + dtb_max, -1, 1);
++
++			dbgprintf("initrd: base %lx, size %lxh (%ld)\n",
++				initrd_base, initrd_size, initrd_size);
++
++			if (initrd_base == ULONG_MAX)
++				return -ENOMEM;
++
++			result = dtb_set_initrd((char **)&dtb_2.buf,
++				&dtb_2.size, initrd_base,
++				initrd_base + initrd_size);
++
++			if (result)
++				return result;
++
++			purgatory_base = initrd_base + initrd_size;
++		}
++	}
++
++	if (dtb_2.size > dtb_max) {
++		fprintf(stderr, "%s: Error: Too many DTB mods.\n", __func__);
++		return -EINVAL;
++	}
++
++	add_segment_phys_virt(info, dtb_2.buf, dtb_2.size, dtb_base,
++		dtb_2.size, 0);
++
++	if (arm64_opts.initrd)
++		add_segment_phys_virt(info, initrd_buf, initrd_size,
++				initrd_base, initrd_size, 0);
++
++	if (arm64_opts.lite) {
++		fprintf(stderr, "kexec: --lite option currently NOT SUPPORTED.\n");
++		return -ENOSYS;
++	} else {
++		result = build_elf_rel_info(purgatory, purgatory_size, &ehdr,
++			0);
++
++		if (result < 0) {
++			fprintf(stderr, "%s: Error: "
++				"build_elf_rel_info failed.\n", __func__);
++			return -EBADF;
++		}
++
++		elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
++			purgatory_base, ULONG_MAX, 1, 0);
++
++		info->entry = (void *)elf_rel_get_addr(&info->rhdr,
++			"purgatory_start");
++
++		elf_rel_set_symbol(&info->rhdr, "arm64_sink", &purgatory_sink,
++			sizeof(purgatory_sink));
++
++		elf_rel_set_symbol(&info->rhdr, "arm64_kernel_entry",
++			&kernel_entry, sizeof(kernel_entry));
++
++		elf_rel_set_symbol(&info->rhdr, "arm64_dtb_addr", &dtb_base,
++				sizeof(dtb_base));
++	}
++
++	return 0;
++}
++
++unsigned long virt_to_phys(unsigned long v)
++{
++	unsigned long p;
++
++	assert(arm64_mem.page_offset);
++	assert(check_memstart());
++
++	p = v - arm64_mem.page_offset + arm64_mem.memstart;
++
++	dbgprintf("%s: %016lx -> %016lx\n", __func__, v, p);
++	return p;
++}
++
++unsigned long phys_to_virt(struct crash_elf_info *UNUSED(elf_info),
++	unsigned long p)
++{
++	unsigned long v;
++
++	assert(arm64_mem.page_offset);
++	assert(check_memstart());
++
++	v = p - arm64_mem.memstart + arm64_mem.page_offset;
++
++	dbgprintf("%s: %016lx -> %016lx\n", __func__, p, v);
++	return p;
++}
++
++void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
++	unsigned long base, size_t memsz)
++{
++	add_segment_phys_virt(info, buf, bufsz, base, memsz, 1);
++}
++
++int arm64_process_image_header(const struct arm64_image_header *h)
++{
++#if !defined(KERNEL_IMAGE_SIZE)
++# define KERNEL_IMAGE_SIZE (768 * 1024)
++#endif
++
++	if (!arm64_header_check_magic(h))
++		return -EINVAL;
++
++	if (h->image_size) {
++		arm64_mem.text_offset = le64_to_cpu(h->text_offset);
++		arm64_mem.image_size = le64_to_cpu(h->image_size);
++	} else {
++		/* For 3.16 and older kernels. */
++		arm64_mem.text_offset = 0x80000;
++		arm64_mem.image_size = KERNEL_IMAGE_SIZE;
++	}
++
++	return 0;
++}
++
++static int get_memory_ranges_dt(struct memory_range *array, unsigned int *count)
++{
++	struct region {uint64_t base; uint64_t size;};
++	struct dtb dtb = {.name = "range_dtb"};
++	int offset;
++	int result;
++
++	*count = 0;
++
++	result = read_1st_dtb(&dtb, NULL);
++
++	if (result) {
++		goto on_error;
++	}
++
++	result = fdt_check_header(dtb.buf);
++
++	if (result) {
++		dbgprintf("%s:%d: %s: fdt_check_header failed:%s\n", __func__,
++			__LINE__, dtb.path, fdt_strerror(result));
++		goto on_error;
++	}
++
++	for (offset = 0; ; ) {
++		const struct region *region;
++		const struct region *end;
++		int len;
++
++		offset = fdt_subnode_offset(dtb.buf, offset, "memory");
++
++		if (offset == -FDT_ERR_NOTFOUND)
++			break;
++
++		if (offset <= 0) {
++			dbgprintf("%s:%d: fdt_subnode_offset failed: %d %s\n",
++				__func__, __LINE__, offset,
++				fdt_strerror(offset));
++			goto on_error;
++		}
++
++		dbgprintf("%s:%d: node_%d %s\n", __func__, __LINE__, offset,
++			fdt_get_name(dtb.buf, offset, NULL));
++
++		region = fdt_getprop(dtb.buf, offset, "reg", &len);
++
++		if (region <= 0) {
++			dbgprintf("%s:%d: fdt_getprop failed: %d %s\n",
++				__func__, __LINE__, offset,
++				fdt_strerror(offset));
++			goto on_error;
++		}
++
++		for (end = region + len / sizeof(*region);
++			region < end && *count < KEXEC_SEGMENT_MAX;
++			region++) {
++			struct memory_range r;
++
++			r.type = RANGE_RAM;
++			r.start = fdt64_to_cpu(region->base);
++			r.end = r.start + fdt64_to_cpu(region->size);
++
++			if (!region->size) {
++				dbgprintf("%s:%d: SKIP: %016llx - %016llx\n",
++					__func__, __LINE__, r.start, r.end);
++				continue;
++			}
++
++			dbgprintf("%s:%d:  RAM: %016llx - %016llx\n", __func__,
++				__LINE__, r.start, r.end);
++
++			array[(*count)++] = r;
++
++			set_memstart(r.start);
++		}
++	}
++
++	if (!*count) {
++		dbgprintf("%s:%d: %s: No RAM found.\n", __func__, __LINE__,
++			dtb.path);
++		goto on_error;
++	}
++
++	dbgprintf("%s:%d: %s: Success\n", __func__, __LINE__, dtb.path);
++	result = 0;
++	goto on_exit;
++
++on_error:
++	fprintf(stderr, "%s:%d: %s: Unusable device-tree file\n", __func__,
++		__LINE__, dtb.path);
++	result = -1;
++
++on_exit:
++	free(dtb.buf);
++	return result;
++}
++
++static int get_memory_ranges_iomem(struct memory_range *array,
++	unsigned int *count)
++{
++	const char *iomem;
++	char line[MAX_LINE];
++	FILE *fp;
++
++	*count = 0;
++
++	iomem = proc_iomem();
++	fp = fopen(iomem, "r");
++
++	if (!fp) {
++		fprintf(stderr, "Cannot open %s: %s\n", iomem, strerror(errno));
++		return -1;
++	}
++
++	while(fgets(line, sizeof(line), fp) != 0) {
++		struct memory_range r;
++		char *str;
++		int consumed;
++
++		if (*count >= KEXEC_SEGMENT_MAX)
++			break;
++
++		if (sscanf(line, "%Lx-%Lx : %n", &r.start, &r.end, &consumed)
++			!= 2)
++			continue;
++
++		str = line + consumed;
++		r.end++;
++
++		if (memcmp(str, "System RAM\n", 11)) {
++			dbgprintf("%s:%d: SKIP: %016Lx - %016Lx : %s", __func__,
++				__LINE__, r.start, r.end, str);
++			continue;
++		}
++
++		r.type = RANGE_RAM;
++
++		dbgprintf("%s:%d: RAM:  %016llx - %016llx : %s", __func__,
++			__LINE__, r.start, r.end, str);
++
++		array[(*count)++] = r;
++
++		set_memstart(r.start);
++	}
++
++	fclose(fp);
++
++	if (!*count) {
++		dbgprintf("%s:%d: failed: No RAM found.\n", __func__, __LINE__);
++		return -1;
++	}
++
++	dbgprintf("%s:%d: Success\n", __func__, __LINE__);
++	return 0;
++}
++
++int get_memory_ranges(struct memory_range **range, int *ranges,
++	unsigned long kexec_flags)
++{
++	static struct memory_range array[KEXEC_SEGMENT_MAX];
++	unsigned int count;
++	int result;
++
++	result = get_memory_ranges_dt(array, &count);
++
++	if (result)
++		result = get_memory_ranges_iomem(array, &count);
++
++	*range = result ? NULL : array;
++	*ranges = result ? 0 : count;
++
++	return result;
++}
++
++struct file_type file_type[] = {
++	{"elf-arm64", elf_arm64_probe, elf_arm64_load, elf_arm64_usage},
++	{"image-arm64", image_arm64_probe, image_arm64_load, image_arm64_usage},
++};
++
++int file_types = sizeof(file_type) / sizeof(file_type[0]);
++
++int arch_compat_trampoline(struct kexec_info *info)
++{
++	return 0;
++}
++
++int machine_verify_elf_rel(struct mem_ehdr *ehdr)
++{
++	return (ehdr->e_machine == EM_AARCH64);
++}
++
++void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type,
++	void *ptr, unsigned long address, unsigned long value)
++{
++#if !defined(R_AARCH64_ABS64)
++# define R_AARCH64_ABS64 257
++#endif
++
++#if !defined(R_AARCH64_LD_PREL_LO19)
++# define R_AARCH64_LD_PREL_LO19 273
++#endif
++
++#if !defined(R_AARCH64_ADR_PREL_LO21)
++# define R_AARCH64_ADR_PREL_LO21 274
++#endif
++
++#if !defined(R_AARCH64_JUMP26)
++# define R_AARCH64_JUMP26 282
++#endif
++
++#if !defined(R_AARCH64_CALL26)
++# define R_AARCH64_CALL26 283
++#endif
++
++	uint64_t *location = (uint64_t *)ptr;
++	uint64_t data = *location;
++	const char *type = NULL;
++
++	switch(r_type) {
++	case R_AARCH64_ABS64:
++		type = "ABS64";
++		*location += value;
++		break;
++	case R_AARCH64_LD_PREL_LO19:
++		type = "LD_PREL_LO19";
++		*location += ((value - address) << 3) & 0xffffe0;
++		break;
++	case R_AARCH64_ADR_PREL_LO21:
++		if (value & 3)
++			die("%s: ERROR Unaligned value: %lx\n", __func__,
++				value);
++		type = "ADR_PREL_LO21";
++		*location += ((value - address) << 3) & 0xffffe0;
++		break;
++	case R_AARCH64_JUMP26:
++		type = "JUMP26";
++		*location += ((value - address) >> 2) & 0x3ffffff;
++		break;
++	case R_AARCH64_CALL26:
++		type = "CALL26";
++		*location += ((value - address) >> 2) & 0x3ffffff;
++		break;
++	default:
++		die("%s: ERROR Unknown type: %lu\n", __func__, r_type);
++		break;
++	}
++
++	dbgprintf("%s: %s %lx->%lx\n", __func__, type, data, *location);
++}
++
++void arch_reuse_initrd(void)
++{
++	reuse_initrd = 1;
++}
++
++void arch_update_purgatory(struct kexec_info *UNUSED(info))
++{
++}
+diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
+new file mode 100644
+index 000000000000..057acf313b49
+--- /dev/null
++++ b/kexec/arch/arm64/kexec-arm64.h
+@@ -0,0 +1,51 @@
++/*
++ * ARM64 kexec.
++ */
++
++#if !defined(KEXEC_ARM64_H)
++#define KEXEC_ARM64_H
++
++#include <stdbool.h>
++#include <sys/types.h>
++
++#include "image-header.h"
++#include "kexec.h"
++
++#define KEXEC_SEGMENT_MAX 16
++
++#define BOOT_BLOCK_VERSION 17
++#define BOOT_BLOCK_LAST_COMP_VERSION 16
++#define COMMAND_LINE_SIZE 512
++
++int elf_arm64_probe(const char *kernel_buf, off_t kernel_size);
++int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
++	off_t kernel_size, struct kexec_info *info);
++void elf_arm64_usage(void);
++
++int image_arm64_probe(const char *kernel_buf, off_t kernel_size);
++int image_arm64_load(int argc, char **argv, const char *kernel_buf,
++	off_t kernel_size, struct kexec_info *info);
++void image_arm64_usage(void);
++
++struct memory_ranges usablemem_rgns;
++off_t initrd_base;
++off_t initrd_size;
++
++/**
++ * struct arm64_mem - Memory layout info.
++ */
++
++struct arm64_mem {
++	uint64_t text_offset;
++	uint64_t image_size;
++	uint64_t page_offset;
++	uint64_t memstart;
++};
++
++extern struct arm64_mem arm64_mem;
++
++int arm64_process_image_header(const struct arm64_image_header *h);
++int arm64_load_other_segments(struct kexec_info *info,
++	unsigned long kernel_entry);
++
++#endif
+diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
+new file mode 100644
+index 000000000000..13dc5e2724d9
+--- /dev/null
++++ b/kexec/arch/arm64/kexec-elf-arm64.c
+@@ -0,0 +1,123 @@
++/*
++ * ARM64 kexec elf support.
++ */
++
++#define _GNU_SOURCE
++
++#include <assert.h>
++#include <errno.h>
++#include <getopt.h>
++#include <libfdt.h>
++
++#include <linux/elf.h>
++
++#include "dt-ops.h"
++#include "crashdump-arm64.h"
++#include "kexec-arm64.h"
++#include "fs2dt.h"
++#include "kexec-syscall.h"
++#include "arch/options.h"
++
++int elf_arm64_probe(const char *kernel_buf, off_t kernel_size)
++{
++	int result;
++	struct mem_ehdr ehdr;
++
++	result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0);
++
++	if (result < 0) {
++		dbgprintf("%s: Not an ELF executable.\n", __func__);
++		goto on_exit;
++	}
++
++	if (ehdr.e_machine != EM_AARCH64) {
++		dbgprintf("%s: Not an AARCH64 ELF executable.\n", __func__);
++		result = -EINVAL;
++		goto on_exit;
++	}
++
++	result = 0;
++
++on_exit:
++	free_elf_info(&ehdr);
++	return result;
++}
++
++int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
++	off_t kernel_size, struct kexec_info *info)
++{
++	int result;
++	struct mem_ehdr ehdr;
++	bool found_header;
++	int i;
++
++	if (info->kexec_flags & KEXEC_ON_CRASH) {
++		fprintf(stderr, "kexec: kdump not yet supported on arm64\n");
++		return -EINVAL;
++	}
++
++	result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0);
++
++	if (result < 0) {
++		dbgprintf("%s: build_elf_exec_info failed\n", __func__);
++		goto exit;
++	}
++
++	/* Find and process the arm64 image header. */
++
++	for (i = 0, found_header = false; i < ehdr.e_phnum; i++) {
++		struct mem_phdr *phdr = &ehdr.e_phdr[i];
++		const struct arm64_image_header *h;
++
++		if (phdr->p_type != PT_LOAD)
++			continue;
++
++		h = (const struct arm64_image_header *)(kernel_buf
++			+ phdr->p_offset);
++
++		if (arm64_process_image_header(h))
++			continue;
++
++		found_header = true;
++
++		arm64_mem.page_offset = phdr->p_vaddr - arm64_mem.text_offset;
++
++		dbgprintf("%s: PE format: %s\n", __func__,
++			(arm64_header_check_pe_sig(h) ? "yes" : "no"));
++		dbgprintf("p_vaddr: %016llx\n", phdr->p_vaddr);
++
++		break;
++	}
++
++	if (!found_header) {
++		fprintf(stderr, "kexec: Bad arm64 image header.\n");
++		result = -EINVAL;
++		goto exit;
++	}
++
++	result = elf_exec_load(&ehdr, info);
++
++	if (result) {
++		fprintf(stderr, "kexec: Elf load failed.\n");
++		goto exit;
++	}
++
++	dbgprintf("%s: text_offset: %016lx\n", __func__, arm64_mem.text_offset);
++	dbgprintf("%s: image_size:  %016lx\n", __func__, arm64_mem.image_size);
++	dbgprintf("%s: page_offset: %016lx\n", __func__, arm64_mem.page_offset);
++	dbgprintf("%s: memstart:    %016lx\n", __func__, arm64_mem.memstart);
++	dbgprintf("%s: e_entry:     %016llx -> %016lx\n", __func__,
++		ehdr.e_entry, virt_to_phys(ehdr.e_entry));
++
++	result = arm64_load_other_segments(info, virt_to_phys(ehdr.e_entry));
++exit:
++	free_elf_info(&ehdr);
++	return result;
++}
++
++void elf_arm64_usage(void)
++{
++	printf(
++"     An arm64 ELF file, big or little endian.\n"
++"     Typically vmlinux or a stripped version of vmlinux.\n\n");
++}
+diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
+new file mode 100644
+index 000000000000..b025dc6c0185
+--- /dev/null
++++ b/kexec/arch/arm64/kexec-image-arm64.c
+@@ -0,0 +1,50 @@
++/*
++ * ARM64 kexec binary image support.
++ */
++
++#define _GNU_SOURCE
++
++#include <assert.h>
++#include <errno.h>
++#include <getopt.h>
++#include <libfdt.h>
++
++#include "dt-ops.h"
++#include "image-header.h"
++#include "kexec-arm64.h"
++#include "fs2dt.h"
++#include "kexec-syscall.h"
++#include "arch/options.h"
++
++int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
++{
++	const struct arm64_image_header *h;
++
++	if (kernel_size < sizeof(struct arm64_image_header))
++		return -EINVAL;
++
++	h = (const struct arm64_image_header *)(kernel_buf);
++
++	if (!arm64_header_check_magic(h))
++		return -1;
++
++	dbgprintf("%s: PE format: %s\n", __func__,
++		(arm64_header_check_pe_sig(h) ? "yes" : "no"));
++
++	fprintf(stderr, "kexec: arm64 binary Image files are currently NOT SUPPORTED.\n");
++
++	return -1;
++}
++
++int image_arm64_load(int argc, char **argv, const char *kernel_buf,
++	off_t kernel_size, struct kexec_info *info)
++{
++	return -ENOSYS;
++}
++
++void image_arm64_usage(void)
++{
++	printf(
++"     An arm64 binary Image file, big or little endian.\n"
++"     This file type is currently NOT SUPPORTED.\n\n");
++}
+diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
+index ce2e20b8b04b..267b75b02272 100644
+--- a/kexec/kexec-syscall.h
++++ b/kexec/kexec-syscall.h
+@@ -39,8 +39,8 @@
+ #ifdef __s390__
+ #define __NR_kexec_load		277
+ #endif
+-#ifdef __arm__
+-#define __NR_kexec_load		__NR_SYSCALL_BASE + 347  
++#if defined(__arm__) || defined(__arm64__)
++#define __NR_kexec_load		__NR_SYSCALL_BASE + 347
+ #endif
+ #if defined(__mips__)
+ #define __NR_kexec_load                4311
+@@ -108,6 +108,8 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
+ #define KEXEC_ARCH_PPC64   (21 << 16)
+ #define KEXEC_ARCH_IA_64   (50 << 16)
+ #define KEXEC_ARCH_ARM     (40 << 16)
++#define KEXEC_ARCH_ARM64   (183 << 16)
++/* #define KEXEC_ARCH_AARCH64 (183 << 16) */
+ #define KEXEC_ARCH_S390    (22 << 16)
+ #define KEXEC_ARCH_SH      (42 << 16)
+ #define KEXEC_ARCH_MIPS_LE (10 << 16)
+@@ -153,5 +155,8 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
+ #ifdef __m68k__
+ #define KEXEC_ARCH_NATIVE	KEXEC_ARCH_68K
+ #endif
++#if defined(__arm64__)
++#define KEXEC_ARCH_NATIVE	KEXEC_ARCH_ARM64
++#endif
+ 
+ #endif /* KEXEC_SYSCALL_H */
+diff --git a/purgatory/Makefile b/purgatory/Makefile
+index 19457029e79f..0c85da6e29b8 100644
+--- a/purgatory/Makefile
++++ b/purgatory/Makefile
+@@ -18,6 +18,7 @@ dist += purgatory/Makefile $(PURGATORY_SRCS)				\
+ 
+ include $(srcdir)/purgatory/arch/alpha/Makefile
+ include $(srcdir)/purgatory/arch/arm/Makefile
++include $(srcdir)/purgatory/arch/arm64/Makefile
+ include $(srcdir)/purgatory/arch/i386/Makefile
+ include $(srcdir)/purgatory/arch/ia64/Makefile
+ include $(srcdir)/purgatory/arch/mips/Makefile
+diff --git a/purgatory/arch/arm64/Makefile b/purgatory/arch/arm64/Makefile
+new file mode 100644
+index 000000000000..636abeab17b2
+--- /dev/null
++++ b/purgatory/arch/arm64/Makefile
+@@ -0,0 +1,18 @@
++
++arm64_PURGATORY_EXTRA_CFLAGS = \
++	-mcmodel=large \
++	-fno-stack-protector \
++	-fno-asynchronous-unwind-tables \
++	-Wundef \
++	-Werror-implicit-function-declaration \
++	-Wdeclaration-after-statement \
++	-Werror=implicit-int \
++	-Werror=strict-prototypes
++
++arm64_PURGATORY_SRCS += \
++	purgatory/arch/arm64/entry.S \
++	purgatory/arch/arm64/purgatory-arm64.c
++
++dist += \
++	$(arm64_PURGATORY_SRCS) \
++	purgatory/arch/arm64/Makefile
+diff --git a/purgatory/arch/arm64/entry.S b/purgatory/arch/arm64/entry.S
+new file mode 100644
+index 000000000000..140e91d87ab1
+--- /dev/null
++++ b/purgatory/arch/arm64/entry.S
+@@ -0,0 +1,54 @@
++/*
++ * ARM64 purgatory.
++ */
++
++.macro	debug_brk
++	mov	x0, #0x18;		/* angel_SWIreason_ReportException */
++	mov	x1, #0x20000;
++	add	x1, x1, #0x20;		/* ADP_Stopped_BreakPoint */
++	hlt	#0xf000			/* A64 semihosting */
++.endm
++
++.macro	size, sym:req
++	.size \sym, . - \sym
++.endm
++
++.text
++
++.globl purgatory_start
++purgatory_start:
++
++	adr	x19, .Lstack
++	mov	sp, x19
++
++	bl	purgatory
++
++1:	debug_brk
++	b	1b
++
++size purgatory_start 
++
++.align 4
++	.rept	256
++	.quad	0
++	.endr
++.Lstack:
++
++.data
++
++.align 3
++
++.globl arm64_sink
++arm64_sink:
++	.quad	0
++size arm64_sink
++
++.globl arm64_kernel_entry
++arm64_kernel_entry:
++	.quad	0
++size arm64_kernel_entry
++
++.globl arm64_dtb_addr
++arm64_dtb_addr:
++	.quad	0
++size arm64_dtb_addr
+diff --git a/purgatory/arch/arm64/purgatory-arm64.c b/purgatory/arch/arm64/purgatory-arm64.c
+new file mode 100644
+index 000000000000..25960c30bd05
+--- /dev/null
++++ b/purgatory/arch/arm64/purgatory-arm64.c
+@@ -0,0 +1,35 @@
++/*
++ * ARM64 purgatory.
++ */
++
++#include <stdint.h>
++#include <purgatory.h>
++
++/* Symbols set by kexec. */
++
++extern uint32_t *arm64_sink;
++extern void (*arm64_kernel_entry)(uint64_t);
++extern uint64_t arm64_dtb_addr;
++
++void putchar(int ch)
++{
++	if (!arm64_sink)
++		return;
++
++	*arm64_sink = ch;
++
++	if (ch == '\n')
++		*arm64_sink = '\r';
++}
++
++void setup_arch(void)
++{
++	printf("purgatory: kernel_entry: %lx\n",
++		(unsigned long)arm64_kernel_entry);
++	printf("purgatory: dtb:          %lx\n", arm64_dtb_addr);
++}
++
++void post_verification_setup_arch(void)
++{
++	arm64_kernel_entry(arm64_dtb_addr);
++}
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-Add-enable-disable-d-cache-support-for-purgato.patch b/SOURCES/kexec-tools-2.0.8-arm64-Add-enable-disable-d-cache-support-for-purgato.patch
new file mode 100644
index 0000000..9a65476
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-Add-enable-disable-d-cache-support-for-purgato.patch
@@ -0,0 +1,309 @@
+From 8b40614f4c1925fe94f274dfc69d1a63537fe399 Mon Sep 17 00:00:00 2001
+Message-Id: <8b40614f4c1925fe94f274dfc69d1a63537fe399.1430751022.git.panand@redhat.com>
+From: Pratyush Anand <panand@redhat.com>
+Date: Mon, 4 May 2015 17:43:25 +0530
+Subject: [PATCH 1/3] arm64: Add enable/disable d-cache support for purgatory
+
+This patch adds support to enable/disable d-cache, which can be used for
+faster purgatory sha256 verification.
+
+Signed-off-by: Pratyush Anand <panand@redhat.com>
+---
+ purgatory/arch/arm64/Makefile |   1 +
+ purgatory/arch/arm64/cache.S  | 222 ++++++++++++++++++++++++++++++++++++++++++
+ purgatory/arch/arm64/cache.h  |  42 ++++++++
+ 3 files changed, 265 insertions(+)
+ create mode 100644 purgatory/arch/arm64/cache.S
+ create mode 100644 purgatory/arch/arm64/cache.h
+
+diff --git a/purgatory/arch/arm64/Makefile b/purgatory/arch/arm64/Makefile
+index 5d35161fc5f4..04fef16476fb 100644
+--- a/purgatory/arch/arm64/Makefile
++++ b/purgatory/arch/arm64/Makefile
+@@ -12,6 +12,7 @@ arm64_PURGATORY_EXTRA_CFLAGS = \
+ 
+ arm64_PURGATORY_SRCS += \
+ 	purgatory/arch/arm64/entry.S \
++	purgatory/arch/arm64/cache.S \
+ 	purgatory/arch/arm64/purgatory-arm64.c
+ 
+ dist += \
+diff --git a/purgatory/arch/arm64/cache.S b/purgatory/arch/arm64/cache.S
+new file mode 100644
+index 000000000000..6bbdeacdab47
+--- /dev/null
++++ b/purgatory/arch/arm64/cache.S
+@@ -0,0 +1,222 @@
++/*
++ * Cache maintenance
++ * Some of the routine has been copied from Linux Kernel, therefore
++ * copying the license as well.
++ *
++ * Copyright (C) 2001 Deep Blue Solutions Ltd.
++ * Copyright (C) 2012 ARM Ltd.
++ * Copyright (C) 2015 Pratyush Anand <panand@redhat.com>
++ *
++ * 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.
++ *
++ * 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.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++#include "cache.h"
++
++/*
++ * dcache_line_size - get the minimum D-cache line size from the CTR register.
++ */
++	.macro	dcache_line_size, reg, tmp
++	mrs	\tmp, ctr_el0			// read CTR
++	ubfm	\tmp, \tmp, #16, #19		// cache line size encoding
++	mov	\reg, #4			// bytes per word
++	lsl	\reg, \reg, \tmp		// actual cache line size
++	.endm
++
++/*
++ *	__inval_cache_range(start, end)
++ *	- start	- start address of region
++ *	- end	- end address of region
++ */
++__inval_cache_range:
++	dcache_line_size x2, x3
++	sub	x3, x2, #1
++	tst	x1, x3				// end cache line aligned?
++	bic	x1, x1, x3
++	b.eq	1f
++	dc	civac, x1			// clean & invalidate D / U line
++1:	tst	x0, x3				// start cache line aligned?
++	bic	x0, x0, x3
++	b.eq	2f
++	dc	civac, x0			// clean & invalidate D / U line
++	b	3f
++2:	dc	ivac, x0			// invalidate D / U line
++3:	add	x0, x0, x2
++	cmp	x0, x1
++	b.lo	2b
++	dsb	sy
++	ret
++/*
++ *	__flush_dcache_range(start, end)
++ *	- start	- start address of region
++ *	- end	- end address of region
++ *
++ */
++__flush_dcache_range:
++	dcache_line_size x2, x3
++	sub	x3, x2, #1
++	bic	x0, x0, x3
++1:	dc	civac, x0			// clean & invalidate D line / unified line
++	add	x0, x0, x2
++	cmp	x0, x1
++	b.lo	1b
++	dsb	sy
++	ret
++
++/*
++ *	enable_dcache(start, end, page_table)
++ *	- start	- start address of ram
++ *	- end	- end address of ram
++ *	- page_table - base of page table
++ */
++.globl enable_dcache
++enable_dcache:
++	stp	x6, x7, [sp,#-16]!
++	stp	x16, x17, [sp,#-16]!
++	stp	x18, x19, [sp,#-16]!
++
++	/* save args */
++	mov x16, x0	/* first segment start */
++	mov x17, x1	/* last segment end */
++	mov x18, x2 	/* page table */
++	mov x19, x30	/* save ret addr */
++
++	/*
++	 * Invalidate the page tables to avoid potential
++	 * dirty cache lines being evicted.
++	 */
++	mov x0, x18
++	add x1, x0, #PAGE_TABLE_SIZE
++	bl __inval_cache_range
++
++	/*
++	 * Clear the page tables.
++	 */
++	mov x0, x18
++	add x1, x0, #PAGE_TABLE_SIZE
++1:	stp	xzr, xzr, [x0], #16
++	stp	xzr, xzr, [x0], #16
++	stp	xzr, xzr, [x0], #16
++	stp	xzr, xzr, [x0], #16
++	cmp	x0, x1
++	b.lo	1b
++
++	/*
++	 * Create the identity mapping.
++	 */
++	ldr	x6, =SECTION_SHIFT
++	ldr	x7, =MM_MMUFLAGS
++	lsr	x0, x16, x6	//first index
++	lsr	x1, x17, x6	//last index
++
++next_sect:
++	lsl	x2, x0, x6	//section
++	orr	x2, x2, x7
++	str	x2, [x18, x0, lsl #3]
++	add	x0, x0, #1
++	cmp	x0, x1
++	b.ls	next_sect
++
++	/*
++	 * Since the page tables have been populated with non-cacheable
++	 * accesses (MMU disabled), invalidate the idmap page
++	 * tables again to remove any speculatively loaded cache lines.
++	 */
++	mov x0, x18
++	add x1, x0, #PAGE_TABLE_SIZE
++	bl __inval_cache_range
++
++	mrs 	x0, CurrentEL
++	cmp	x0, #12	//EL3
++	b.eq	set_el3
++	cmp	x0, #8	//EL2
++	b.eq	set_el2
++	cmp	x0, #4	//EL1
++	b.eq	set_el1
++	b	done_enable
++
++set_el1:
++	msr	ttbr0_el1, x18
++	ldr	x0, =TCR_FLAGS
++	orr	x0, x0, #TCR_EL1_IPS_BITS
++	msr	tcr_el1, x0
++	ldr	x0, =MEMORY_ATTRIBUTES
++	msr	mair_el1, x0
++	mrs	x0, sctlr_el1
++	orr	x0, x0, #CR_M
++	orr	x0, x0, #CR_C
++	msr	sctlr_el1, x0
++	b	done_enable
++set_el2:
++	msr	ttbr0_el2, x18
++	ldr	x0, =TCR_FLAGS
++	orr	x0, x0, #TCR_EL2_IPS_BITS
++	msr	tcr_el2, x0
++	ldr	x0, =MEMORY_ATTRIBUTES
++	msr	mair_el2, x0
++	mrs	x0, sctlr_el2
++	orr	x0, x0, #CR_M
++	orr	x0, x0, #CR_C
++	msr	sctlr_el2, x0
++	b	done_enable
++set_el3:
++	msr	ttbr0_el3, x18
++	ldr	x0, =TCR_FLAGS
++	orr	x0, x0, #TCR_EL3_IPS_BITS
++	msr	tcr_el3, x0
++	ldr	x0, =MEMORY_ATTRIBUTES
++	msr	mair_el3, x0
++	mrs	x0, sctlr_el3
++	orr	x0, x0, #CR_M
++	orr	x0, x0, #CR_C
++	msr	sctlr_el3, x0
++done_enable:
++
++	mov	x30, x19
++	ldp	x18, x19, [sp],#16
++	ldp	x16, x17, [sp],#16
++	ldp	x6, x7, [sp],#16
++
++	ret
++
++.globl disable_dcache
++disable_dcache:
++	stp	x5, x30, [sp,#-16]!
++	mrs 	x5, CurrentEL
++	cmp	x5, #12	//EL3
++	b.eq	disable_el3
++	cmp	x5, #8	//EL2
++	b.eq	disable_el2
++	cmp	x5, #4	//EL1
++	b.eq	disable_el1
++	b	done_disable
++disable_el3:
++	mrs	x5, sctlr_el3
++	bic	x5, x2, #CR_M
++	bic	x5, x2, #CR_C
++	msr	sctlr_el3, x5
++	b	done_disable
++disable_el2:
++	mrs	x5, sctlr_el2
++	bic	x5, x2, #CR_M
++	bic	x5, x2, #CR_C
++	msr	sctlr_el2, x5
++	b	done_disable
++disable_el1:
++	mrs	x5, sctlr_el1
++	bic	x5, x2, #CR_M
++	bic	x5, x2, #CR_C
++	msr	sctlr_el1, x5
++done_disable:
++	bl __flush_dcache_range
++	ldp	x5, x30, [sp],#16
++	ret
+diff --git a/purgatory/arch/arm64/cache.h b/purgatory/arch/arm64/cache.h
+new file mode 100644
+index 000000000000..3ca1d7f9a5ca
+--- /dev/null
++++ b/purgatory/arch/arm64/cache.h
+@@ -0,0 +1,42 @@
++#ifndef	__CACHE_H__
++#define __CACHE_H__
++
++#define VA_BITS			42
++#define SECTION_SHIFT		29
++#define PAGE_TABLE_SIZE		(1 << (VA_BITS - SECTION_SHIFT + 3))
++
++#define TCR_TG0_64K 		(1 << 14)
++#define TCR_SHARED_NON		(0 << 12)
++#define TCR_ORGN_WBWA		(1 << 10)
++#define TCR_IRGN_WBWA		(1 << 8)
++#define TCR_T0SZ(x)		((64 - (x)) << 0)
++#define TCR_EL1_IPS_BITS	(3 << 32) /* 42 bits physical address */
++#define TCR_EL2_IPS_BITS	(3 << 16) /* 42 bits physical address */
++#define TCR_EL3_IPS_BITS	(3 << 16) /* 42 bits physical address */
++
++#define TCR_FLAGS (TCR_TG0_64K | TCR_SHARED_NON | TCR_ORGN_WBWA | \
++		TCR_IRGN_WBWA | TCR_T0SZ(VA_BITS))
++
++#define MT_DEVICE_NGNRNE	0
++#define MT_DEVICE_NGNRE		1
++#define MT_DEVICE_GRE		2
++#define MT_NORMAL_NC		3
++#define MT_NORMAL		4
++
++#define MEMORY_ATTRIBUTES	((0x00 << (MT_DEVICE_NGNRNE*8)) | \
++				(0x04 << (MT_DEVICE_NGNRE*8)) | \
++				(0x0c << (MT_DEVICE_GRE*8)) | \
++				(0x44 << (MT_NORMAL_NC*8)) | \
++				(0xff << (MT_NORMAL*8)))
++
++#define CR_M			(1 << 0)	/* MMU enable */
++#define CR_C			(1 << 2)	/* Dcache enable */
++
++
++#define PMD_TYPE_SECT		(1 << 0)
++#define PMD_SECT_AF		(1 << 10)
++#define PMD_ATTRINDX(t)		((t) << 2)
++#define PMD_FLAGS	(PMD_TYPE_SECT | PMD_SECT_AF)
++#define MM_MMUFLAGS	PMD_ATTRINDX(MT_NORMAL) | PMD_FLAGS
++
++#endif
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-Add-support-for-kexec-lite-option.patch b/SOURCES/kexec-tools-2.0.8-arm64-Add-support-for-kexec-lite-option.patch
new file mode 100644
index 0000000..04baeb6
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-Add-support-for-kexec-lite-option.patch
@@ -0,0 +1,58 @@
+From d665fa8c7cb6fa6713bad2633b9cccbad98245bc Mon Sep 17 00:00:00 2001
+Message-Id: <d665fa8c7cb6fa6713bad2633b9cccbad98245bc.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: Geoff Levand <geoff@infradead.org>
+Date: Fri, 17 Apr 2015 10:54:55 -0700
+Subject: [PATCH 04/17] arm64: Add support for kexec --lite option
+
+WARNING: This implementation uses kernel feature not yet merged upstream.  In
+the future I may convert this to use a minimal purgatory that is just a
+trampoline.
+---
+ kexec/arch/arm64/include/arch/options.h | 2 +-
+ kexec/arch/arm64/kexec-arm64.c          | 8 +++-----
+ 2 files changed, 4 insertions(+), 6 deletions(-)
+
+diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h
+index 903b4a1fbd7f..afe3e9827ff3 100644
+--- a/kexec/arch/arm64/include/arch/options.h
++++ b/kexec/arch/arm64/include/arch/options.h
+@@ -29,7 +29,7 @@ static const char arm64_opts_usage[] __attribute__ ((unused)) =
+ "     --command-line=STRING Set the kernel command line to STRING.\n"
+ "     --dtb=FILE            Use FILE as the device tree blob.\n"
+ "     --initrd=FILE         Use FILE as the kernel initial ramdisk.\n"
+-"     --lite                Fast reboot, no memory integrity checks - currently NOT SUPPORTED.\n");
++"     --lite                Fast reboot, no memory integrity checks.\n"
+ "     --port=ADDRESS        Purgatory output to port ADDRESS.\n"
+ "     --ramdisk=FILE        Use FILE as the kernel initial ramdisk.\n"
+ "     --reuse-cmdline       Use command line arg of primary kernel.\n";
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+index 22d70244f8db..6398e55fe575 100644
+--- a/kexec/arch/arm64/kexec-arm64.c
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -96,7 +96,6 @@ int arch_process_options(int argc, char **argv)
+ 			break;
+ 		case OPT_LITE:
+ 			arm64_opts.lite = 1;
+-			fprintf(stderr, "kexec: --lite option currently NOT SUPPORTED.\n");
+ 			break;
+ 		case OPT_PORT:
+ 			arm64_opts.port = strtoull(optarg, NULL, 0);
+@@ -702,10 +701,9 @@ int arm64_load_other_segments(struct kexec_info *info,
+ 		add_segment_phys_virt(info, initrd_buf, initrd_size,
+ 				initrd_base, initrd_size, 0);
+ 
+-	if (arm64_opts.lite) {
+-		fprintf(stderr, "kexec: --lite option currently NOT SUPPORTED.\n");
+-		return -ENOSYS;
+-	} else {
++	if (arm64_opts.lite)
++		info->entry = (void *)kernel_entry;
++	else {
+ 		result = build_elf_rel_info(purgatory, purgatory_size, &ehdr,
+ 			0);
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-Add-support-for-reuse-cmdline-option.patch b/SOURCES/kexec-tools-2.0.8-arm64-Add-support-for-reuse-cmdline-option.patch
new file mode 100644
index 0000000..52ba3c3
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-Add-support-for-reuse-cmdline-option.patch
@@ -0,0 +1,82 @@
+From 0730d377b6a6f6cdac25f26016a95db8a9333802 Mon Sep 17 00:00:00 2001
+Message-Id: <0730d377b6a6f6cdac25f26016a95db8a9333802.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: Pratyush Anand <panand@redhat.com>
+Date: Fri, 17 Apr 2015 10:54:55 -0700
+Subject: [PATCH 03/17] arm64: Add support for --reuse-cmdline option
+
+Signed-off-by: Pratyush Anand <panand@redhat.com>
+Signed-off-by: Geoff Levand <geoff@infradead.org>
+---
+ kexec/arch/arm64/include/arch/options.h | 7 +++++--
+ kexec/arch/arm64/kexec-arm64.c          | 8 +++++++-
+ 2 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h
+index 51afc5f1f6f2..903b4a1fbd7f 100644
+--- a/kexec/arch/arm64/include/arch/options.h
++++ b/kexec/arch/arm64/include/arch/options.h
+@@ -6,7 +6,8 @@
+ #define OPT_INITRD	((OPT_MAX)+2)
+ #define OPT_LITE	((OPT_MAX)+3)
+ #define OPT_PORT	((OPT_MAX)+4)
+-#define OPT_ARCH_MAX	((OPT_MAX)+5)
++#define OPT_REUSE_CMDLINE	((OPT_MAX+5))
++#define OPT_ARCH_MAX	((OPT_MAX)+6)
+ 
+ #define KEXEC_ARCH_OPTIONS \
+ 	KEXEC_OPTIONS \
+@@ -17,6 +18,7 @@
+ 	{ "lite",         0, NULL, OPT_LITE }, \
+ 	{ "port",         1, NULL, OPT_PORT }, \
+ 	{ "ramdisk",      1, NULL, OPT_INITRD }, \
++	{ "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \
+ 
+ #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */
+ #define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS
+@@ -29,7 +31,8 @@ static const char arm64_opts_usage[] __attribute__ ((unused)) =
+ "     --initrd=FILE         Use FILE as the kernel initial ramdisk.\n"
+ "     --lite                Fast reboot, no memory integrity checks - currently NOT SUPPORTED.\n");
+ "     --port=ADDRESS        Purgatory output to port ADDRESS.\n"
+-"     --ramdisk=FILE        Use FILE as the kernel initial ramdisk.\n";
++"     --ramdisk=FILE        Use FILE as the kernel initial ramdisk.\n"
++"     --reuse-cmdline       Use command line arg of primary kernel.\n";
+ 
+ struct arm64_opts {
+ 	const char *command_line;
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+index 0860810b6e86..22d70244f8db 100644
+--- a/kexec/arch/arm64/kexec-arm64.c
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -75,13 +75,18 @@ int arch_process_options(int argc, char **argv)
+ 		{ 0 }
+ 	};
+ 	int opt;
++	const char *append = NULL;
++	char *tmp_cmdline = NULL;
+ 
+ 	for (opt = 0; opt != -1; ) {
+ 		opt = getopt_long(argc, argv, short_options, options, 0);
+ 
+ 		switch (opt) {
+ 		case OPT_APPEND:
+-			arm64_opts.command_line = optarg;
++			append = optarg;
++			break;
++		case OPT_REUSE_CMDLINE:
++			tmp_cmdline = get_command_line();
+ 			break;
+ 		case OPT_DTB:
+ 			arm64_opts.dtb = optarg;
+@@ -101,6 +106,7 @@ int arch_process_options(int argc, char **argv)
+ 		}
+ 	}
+ 
++	arm64_opts.command_line = concat_cmdline(tmp_cmdline, append);
+ 	kexec_debug = 1; // FIXME: for debugging only.
+ 
+ 	dbgprintf("%s:%d: command_line: %s\n", __func__, __LINE__,
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-Enable-disable-D-cache-before-after-sha-verifi.patch b/SOURCES/kexec-tools-2.0.8-arm64-Enable-disable-D-cache-before-after-sha-verifi.patch
new file mode 100644
index 0000000..e21d5ae
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-Enable-disable-D-cache-before-after-sha-verifi.patch
@@ -0,0 +1,70 @@
+From 2939844d0211a820cf22a8d666df90af889ec6f1 Mon Sep 17 00:00:00 2001
+Message-Id: <2939844d0211a820cf22a8d666df90af889ec6f1.1430751022.git.panand@redhat.com>
+In-Reply-To: <8b40614f4c1925fe94f274dfc69d1a63537fe399.1430751022.git.panand@redhat.com>
+References: <8b40614f4c1925fe94f274dfc69d1a63537fe399.1430751022.git.panand@redhat.com>
+From: Pratyush Anand <panand@redhat.com>
+Date: Mon, 4 May 2015 17:50:21 +0530
+Subject: [PATCH 3/3] arm64: Enable/disable D-cache before/after sha
+ verification
+
+Enable D cache before SHA verification and disable it before switching
+to kernel.
+
+Since we only map RAM area, therefore currently no printf is allowed
+between d-cache enable and disable events. Identity mapping for port
+area with device type memory attributes need to be created for printf to
+work.
+
+Signed-off-by: Pratyush Anand <panand@redhat.com>
+---
+ purgatory/arch/arm64/purgatory-arm64.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/purgatory/arch/arm64/purgatory-arm64.c b/purgatory/arch/arm64/purgatory-arm64.c
+index 3a1c9243bfa2..e045039039b6 100644
+--- a/purgatory/arch/arm64/purgatory-arm64.c
++++ b/purgatory/arch/arm64/purgatory-arm64.c
+@@ -2,6 +2,7 @@
+  * ARM64 purgatory.
+  */
+ 
++#include "cache.h"
+ #include <stdint.h>
+ #include <purgatory.h>
+ 
+@@ -10,6 +11,8 @@
+ extern uint32_t *arm64_sink;
+ extern void (*arm64_kernel_entry)(uint64_t);
+ extern uint64_t arm64_dtb_addr;
++extern uint64_t arm64_ram_start;
++extern uint64_t arm64_ram_end;
+ 
+ static void wait_for_xmit_complete(void)
+ {
+@@ -44,14 +47,23 @@ void putchar(int ch)
+ 	}
+ }
+ 
++uint64_t page_table[PAGE_TABLE_SIZE / sizeof(uint64_t)] __attribute__ ((aligned (PAGE_TABLE_SIZE))) = { };
++extern void enable_dcache(uint64_t , uint64_t , uint64_t *);
++extern void disable_dcache(uint64_t , uint64_t);
++
+ void setup_arch(void)
+ {
+ 	printf("purgatory: kernel_entry: %lx\n",
+ 		(unsigned long)arm64_kernel_entry);
+ 	printf("purgatory: dtb:          %lx\n", arm64_dtb_addr);
++	printf("purgatory: RAM start: %lx\n", arm64_ram_start);
++	printf("purgatory: RAM end: %lx\n", arm64_ram_end);
++
++	enable_dcache(arm64_ram_start, arm64_ram_end, page_table);
+ }
+ 
+ void post_verification_setup_arch(void)
+ {
++	disable_dcache(arm64_ram_start, arm64_ram_end);
+ 	arm64_kernel_entry(arm64_dtb_addr);
+ }
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-Kexec-Add-support-for-binary-image.patch b/SOURCES/kexec-tools-2.0.8-arm64-Kexec-Add-support-for-binary-image.patch
new file mode 100644
index 0000000..1461967
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-Kexec-Add-support-for-binary-image.patch
@@ -0,0 +1,201 @@
+From 6dd781cca908aea5f282b5c980d806c2f35ea171 Mon Sep 17 00:00:00 2001
+Message-Id: <6dd781cca908aea5f282b5c980d806c2f35ea171.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: Pratyush Anand <panand@redhat.com>
+Date: Mon, 13 Apr 2015 17:19:49 +0530
+Subject: [PATCH 05/17] arm64: Kexec: Add support for binary image
+
+This patch adds support to use binary image ie arch/arm64/boot/Image.
+
+Binary image does not have sufficient knowledge to extract page offset
+information, which is needed by kexec tool. Use a new command parameter
+--page-offset, so that user can provide page offset information for
+linear mapping.
+
+Signed-off-by: Pratyush Anand <panand@redhat.com>
+---
+ kexec/arch/arm64/include/arch/options.h |  9 ++--
+ kexec/arch/arm64/kexec-arm64.c          |  3 ++
+ kexec/arch/arm64/kexec-arm64.h          |  2 +
+ kexec/arch/arm64/kexec-image-arm64.c    | 86 +++++++++++++++++++++++++++++++--
+ 4 files changed, 93 insertions(+), 7 deletions(-)
+
+diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h
+index afe3e9827ff3..fa4ad2c68642 100644
+--- a/kexec/arch/arm64/include/arch/options.h
++++ b/kexec/arch/arm64/include/arch/options.h
+@@ -5,9 +5,10 @@
+ #define OPT_DTB		((OPT_MAX)+1)
+ #define OPT_INITRD	((OPT_MAX)+2)
+ #define OPT_LITE	((OPT_MAX)+3)
+-#define OPT_PORT	((OPT_MAX)+4)
+-#define OPT_REUSE_CMDLINE	((OPT_MAX+5))
+-#define OPT_ARCH_MAX	((OPT_MAX)+6)
++#define OPT_PAGE_OFFSET	((OPT_MAX)+4)
++#define OPT_PORT	((OPT_MAX)+5)
++#define OPT_REUSE_CMDLINE	((OPT_MAX+6))
++#define OPT_ARCH_MAX	((OPT_MAX)+7)
+ 
+ #define KEXEC_ARCH_OPTIONS \
+ 	KEXEC_OPTIONS \
+@@ -16,6 +17,7 @@
+ 	{ "dtb",          1, NULL, OPT_DTB }, \
+ 	{ "initrd",       1, NULL, OPT_INITRD }, \
+ 	{ "lite",         0, NULL, OPT_LITE }, \
++	{ "page-offset",  1, NULL, OPT_PAGE_OFFSET }, \
+ 	{ "port",         1, NULL, OPT_PORT }, \
+ 	{ "ramdisk",      1, NULL, OPT_INITRD }, \
+ 	{ "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \
+@@ -38,6 +40,7 @@ struct arm64_opts {
+ 	const char *command_line;
+ 	const char *dtb;
+ 	const char *initrd;
++	uint64_t page_offset;
+ 	uint64_t port;
+ 	int lite;
+ };
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+index 6398e55fe575..86408598a465 100644
+--- a/kexec/arch/arm64/kexec-arm64.c
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -100,6 +100,9 @@ int arch_process_options(int argc, char **argv)
+ 		case OPT_PORT:
+ 			arm64_opts.port = strtoull(optarg, NULL, 0);
+ 			break;
++		case OPT_PAGE_OFFSET:
++			arm64_opts.page_offset = strtoull(optarg, NULL, 0);
++			break;
+ 		default:
+ 			break; /* Ignore core and unknown options. */
+ 		}
+diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
+index 057acf313b49..7f0ca13fec11 100644
+--- a/kexec/arch/arm64/kexec-arm64.h
++++ b/kexec/arch/arm64/kexec-arm64.h
+@@ -17,6 +17,8 @@
+ #define BOOT_BLOCK_LAST_COMP_VERSION 16
+ #define COMMAND_LINE_SIZE 512
+ 
++#define ARM64_DEFAULT_PAGE_OFFSET 0xfffffe0000000000
++
+ int elf_arm64_probe(const char *kernel_buf, off_t kernel_size);
+ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+ 	off_t kernel_size, struct kexec_info *info);
+diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
+index b025dc6c0185..c577b96d5e31 100644
+--- a/kexec/arch/arm64/kexec-image-arm64.c
++++ b/kexec/arch/arm64/kexec-image-arm64.c
+@@ -8,6 +8,7 @@
+ #include <errno.h>
+ #include <getopt.h>
+ #include <libfdt.h>
++#include <stdlib.h>
+ 
+ #include "dt-ops.h"
+ #include "image-header.h"
+@@ -31,20 +32,97 @@ int image_arm64_probe(const char *kernel_buf, off_t kernel_size)
+ 	dbgprintf("%s: PE format: %s\n", __func__,
+ 		(arm64_header_check_pe_sig(h) ? "yes" : "no"));
+ 
+-	fprintf(stderr, "kexec: arm64 binary Image files are currently NOT SUPPORTED.\n");
++	return 0;
++}
++
++static unsigned long long get_kernel_text_sym(void)
++{
++	const char *kallsyms = "/proc/kallsyms";
++	const char *text = "_text";
++	char sym[128];
++	char line[128];
++	FILE *fp;
++	unsigned long long vaddr;
++	char type;
+ 
+-	return -1;
++	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, text) == 0) {
++			dbgprintf("kernel symbol %s vaddr = %16llx\n", text, vaddr);
++			return vaddr;
++		}
++	}
++
++	fprintf(stderr, "Cannot get kernel %s symbol address\n", text);
++	return 0;
++}
++
++static unsigned long long get_kernel_page_offset(void)
++{
++	unsigned long long text_sym_addr = get_kernel_text_sym();
++	unsigned long long text_page_offset =
++		text_sym_addr & 0xFFFFFFFFFFE00000;
++
++	if(arm64_opts.page_offset) {
++		if (text_page_offset != arm64_opts.page_offset)
++			dbgprintf("User page offset %lx did not match with text page offset %llx\n",
++					arm64_opts.page_offset, text_page_offset); 
++		return arm64_opts.page_offset;
++	} else if(text_page_offset) {
++		dbgprintf("text page offset is %llx\n", text_page_offset);
++		return text_page_offset;
++	} else {
++		return ARM64_DEFAULT_PAGE_OFFSET;
++	}
+ }
+ 
+ int image_arm64_load(int argc, char **argv, const char *kernel_buf,
+ 	off_t kernel_size, struct kexec_info *info)
+ {
+-	return -ENOSYS;
++	int result;
++	uint64_t start;
++	const struct arm64_image_header *h;
++	char *header_option = NULL;
++
++	h = (const struct arm64_image_header *)(kernel_buf);
++
++	arm64_mem.text_offset = le64_to_cpu(h->text_offset);
++	arm64_mem.image_size = le64_to_cpu(h->image_size);
++
++	arm64_mem.page_offset = get_kernel_page_offset();
++
++	result = parse_iomem_single("Kernel code\n", &start, NULL);
++
++	if (result) {
++		fprintf(stderr, "kexec: Could not get kernel code address.\n");
++		return -1;
++	}
++	start -= arm64_mem.text_offset;
++
++	/* Add kernel */
++	add_segment_phys_virt(info, kernel_buf, kernel_size,
++			start + arm64_mem.text_offset,
++			kernel_size, 0);
++
++	info->entry = (void *)start + arm64_mem.text_offset;
++
++	result = arm64_load_other_segments(info, (unsigned long)info->entry);
++
++	if (header_option)
++		free(header_option);
++
++	return result;
+ }
+ 
+ void image_arm64_usage(void)
+ {
+ 	printf(
+ "     An arm64 binary Image file, big or little endian.\n"
+-"     This file type is currently NOT SUPPORTED.\n\n");
++"     --page-offset         Kernel page-offset for binary image load.\n");
+ }
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-Pass-RAM-boundary-to-purgatory.patch b/SOURCES/kexec-tools-2.0.8-arm64-Pass-RAM-boundary-to-purgatory.patch
new file mode 100644
index 0000000..424beaa
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-Pass-RAM-boundary-to-purgatory.patch
@@ -0,0 +1,105 @@
+From 04a2b7bb55bfee0495cc39796846adf8d6a313bc Mon Sep 17 00:00:00 2001
+Message-Id: <04a2b7bb55bfee0495cc39796846adf8d6a313bc.1430751022.git.panand@redhat.com>
+In-Reply-To: <8b40614f4c1925fe94f274dfc69d1a63537fe399.1430751022.git.panand@redhat.com>
+References: <8b40614f4c1925fe94f274dfc69d1a63537fe399.1430751022.git.panand@redhat.com>
+From: Pratyush Anand <panand@redhat.com>
+Date: Mon, 4 May 2015 17:47:14 +0530
+Subject: [PATCH 2/3] arm64: Pass RAM boundary to purgatory
+
+RAM boundary which includes all the sections is needed for creating
+identity page mapping and to enable d-cache for those areas.
+
+Signed-off-by: Pratyush Anand <panand@redhat.com>
+---
+ kexec/arch/arm64/include/types.h | 16 ++++++++++++++++
+ kexec/arch/arm64/kexec-arm64.c   | 16 +++++++++++++++-
+ purgatory/arch/arm64/entry.S     | 10 ++++++++++
+ 3 files changed, 41 insertions(+), 1 deletion(-)
+ create mode 100644 kexec/arch/arm64/include/types.h
+
+diff --git a/kexec/arch/arm64/include/types.h b/kexec/arch/arm64/include/types.h
+new file mode 100644
+index 000000000000..08f833a6d585
+--- /dev/null
++++ b/kexec/arch/arm64/include/types.h
+@@ -0,0 +1,16 @@
++#ifndef _TYPES_H_
++#define _TYPES_H_
++
++#define min(x,y) ({ \
++	typeof(x) _x = (x);	\
++	typeof(y) _y = (y);	\
++	(void) (&_x == &_y);	\
++	_x < _y ? _x : _y; })
++
++#define max(x,y) ({ \
++	typeof(x) _x = (x);	\
++	typeof(y) _y = (y);	\
++	(void) (&_x == &_y);	\
++	_x > _y ? _x : _y; })
++
++#endif /* _TYPES_H_ */
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+index 12c589f8001c..8ce4a61fc9c2 100644
+--- a/kexec/arch/arm64/kexec-arm64.c
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -28,6 +28,7 @@
+ #include "fs2dt.h"
+ #include "kexec-syscall.h"
+ #include "arch/options.h"
++#include "types.h"
+ 
+ /* Global varables the core kexec routines expect. */
+ 
+@@ -588,9 +589,11 @@ static uint64_t read_sink(const char *command_line)
+ int arm64_load_other_segments(struct kexec_info *info,
+ 	unsigned long kernel_entry, char *option)
+ {
+-	int result;
++	int result, i;
+ 	struct mem_ehdr ehdr;
+ 	unsigned long dtb_base;
++	unsigned long arm64_ram_start = -1;
++	unsigned long arm64_ram_end = 0;
+ 	unsigned long hole_min, hole_max;
+ 	char *initrd_buf = NULL;
+ 	uint64_t purgatory_sink;
+@@ -720,6 +723,17 @@ int arm64_load_other_segments(struct kexec_info *info,
+ 
+ 		elf_rel_set_symbol(&info->rhdr, "arm64_dtb_addr", &dtb_base,
+ 				sizeof(dtb_base));
++		for (i = 0; i < info->nr_segments; i++) {
++			arm64_ram_start = min(arm64_ram_start,
++					(unsigned long)info->segment[i].mem);
++			arm64_ram_end = max(arm64_ram_end,
++				((unsigned long)info->segment[i].mem + 
++				info->segment[i].memsz));
++		}
++		elf_rel_set_symbol(&info->rhdr, "arm64_ram_start",
++				&arm64_ram_start, sizeof(arm64_ram_start));
++		elf_rel_set_symbol(&info->rhdr, "arm64_ram_end",
++				&arm64_ram_end, sizeof(arm64_ram_end));
+ 	}
+ 
+ 	return 0;
+diff --git a/purgatory/arch/arm64/entry.S b/purgatory/arch/arm64/entry.S
+index 140e91d87ab1..0713ccdec4ad 100644
+--- a/purgatory/arch/arm64/entry.S
++++ b/purgatory/arch/arm64/entry.S
+@@ -52,3 +52,13 @@ size arm64_kernel_entry
+ arm64_dtb_addr:
+ 	.quad	0
+ size arm64_dtb_addr
++
++.globl arm64_ram_start
++arm64_ram_start:
++	.quad	0
++size arm64_ram_start
++
++.globl arm64_ram_end
++arm64_ram_end:
++	.quad	0
++size arm64_ram_end
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-clean-up-on-crash-dump.patch b/SOURCES/kexec-tools-2.0.8-arm64-clean-up-on-crash-dump.patch
new file mode 100644
index 0000000..c2af525
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-clean-up-on-crash-dump.patch
@@ -0,0 +1,98 @@
+From 359dec003b758e4d950de965f76ecaf6d81c007d Mon Sep 17 00:00:00 2001
+Message-Id: <359dec003b758e4d950de965f76ecaf6d81c007d.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: AKASHI Takahiro <takahiro.akashi@linaro.org>
+Date: Wed, 22 Apr 2015 11:20:27 +0900
+Subject: [PATCH 12/17] arm64: clean up on crash dump
+
+---
+ kexec/arch/arm64/crashdump-arm64.c | 12 +++---------
+ kexec/arch/arm64/crashdump-arm64.h |  6 +++---
+ kexec/arch/arm64/kexec-elf-arm64.c |  9 +++++----
+ 3 files changed, 11 insertions(+), 16 deletions(-)
+
+diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
+index 04958418ae82..a929b9e3ecb1 100644
+--- a/kexec/arch/arm64/crashdump-arm64.c
++++ b/kexec/arch/arm64/crashdump-arm64.c
+@@ -288,7 +288,7 @@ int load_crashdump_segments(struct kexec_info *info, char **option)
+ 	return 0;
+ }
+ 
+-void modify_ehdr_for_crashmem(struct mem_ehdr *ehdr)
++void modify_ehdr_for_crashdump(struct mem_ehdr *ehdr)
+ {
+ 	struct mem_phdr *phdr;
+ 	int i;
+@@ -304,13 +304,7 @@ void modify_ehdr_for_crashmem(struct mem_ehdr *ehdr)
+ 	}
+ }
+ 
+-void set_crash_entry(struct mem_ehdr *ehdr, struct kexec_info *info)
++void *get_crash_entry(void)
+ {
+-	info->entry = (void *)crash_reserved_mem.start + arm64_mem.text_offset;
+-}
+-
+-off_t locate_dtb_in_crashmem(struct kexec_info *info, off_t dtb_size)
+-{
+-	return locate_hole(info, dtb_size, 128UL * 1024,
+-		crash_reserved_mem.start, crash_reserved_mem.end, -1);
++	return (void *)crash_reserved_mem.start + arm64_mem.text_offset;
+ }
+diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
+index d4fd3f2288c9..6457ea7cabec 100644
+--- a/kexec/arch/arm64/crashdump-arm64.h
++++ b/kexec/arch/arm64/crashdump-arm64.h
+@@ -17,10 +17,10 @@
+ #define CRASH_MAX_MEMORY_RANGES	32
+ 
+ extern struct memory_ranges usablemem_rgns;
++extern struct memory_range crash_reserved_mem;
+ 
+ int load_crashdump_segments(struct kexec_info *info, char **option);
+-void modify_ehdr_for_crashmem(struct mem_ehdr *ehdr);
+-void set_crash_entry(struct mem_ehdr *ehdr, struct kexec_info *info);
+-off_t locate_dtb_in_crashmem(struct kexec_info *info, off_t dtb_size);
++void modify_ehdr_for_crashdump(struct mem_ehdr *ehdr);
++void *get_crash_entry(void);
+ 
+ #endif
+diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
+index f5ecda825278..9fda5e539471 100644
+--- a/kexec/arch/arm64/kexec-elf-arm64.c
++++ b/kexec/arch/arm64/kexec-elf-arm64.c
+@@ -93,16 +93,17 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+ 	}
+ 
+ 	if (info->kexec_flags & KEXEC_ON_CRASH) {
++		/* allocate and initialize elf core header */
+ 		result = load_crashdump_segments(info, &header_option);
+ 
+ 		if (result) {
+ 			fprintf(stderr, "kexec: creating eflcorehdr failed.\n");
+ 			goto exit;
+ 		}
+-	}
+ 
+-	if (info->kexec_flags & KEXEC_ON_CRASH)
+-		modify_ehdr_for_crashmem(&ehdr);
++		/* offset addresses to load vmlinux(elf_exec) in crash memory */
++		modify_ehdr_for_crashdump(&ehdr);
++	}
+ 
+ 	result = elf_exec_load(&ehdr, info);
+ 
+@@ -112,7 +113,7 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+ 	}
+ 
+ 	if (info->kexec_flags & KEXEC_ON_CRASH)
+-		set_crash_entry(&ehdr, info);
++		info->entry = get_crash_entry();
+ 	else
+ 		info->entry = (void *)virt_to_phys(ehdr.e_entry);
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-fix-elf-related-header-issues.patch b/SOURCES/kexec-tools-2.0.8-arm64-fix-elf-related-header-issues.patch
new file mode 100644
index 0000000..0fadd22
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-fix-elf-related-header-issues.patch
@@ -0,0 +1,71 @@
+From edac28173d05a547ad20442991ffd7708eba10bb Mon Sep 17 00:00:00 2001
+Message-Id: <edac28173d05a547ad20442991ffd7708eba10bb.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: AKASHI Takahiro <takahiro.akashi@linaro.org>
+Date: Tue, 17 Feb 2015 15:53:07 +0900
+Subject: [PATCH 07/17] arm64: fix elf-related header issues
+
+- add a missing EM_AARCH64 macro
+- linux/elf.h was also replaced with elf.h because they are conflicting
+  each other.
+---
+ include/elf.h                      | 1 +
+ kexec/arch/arm64/kexec-arm64.c     | 3 +--
+ kexec/arch/arm64/kexec-elf-arm64.c | 3 +--
+ 3 files changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/include/elf.h b/include/elf.h
+index 5db637ba2f60..cd2802ae1091 100644
+--- a/include/elf.h
++++ b/include/elf.h
+@@ -259,6 +259,7 @@ typedef struct
+ #define EM_ARC_A5	93		/* ARC Cores Tangent-A5 */
+ #define EM_XTENSA	94		/* Tensilica Xtensa Architecture */
+ #define EM_NUM		95
++#define EM_AARCH64	183		/* ARMv8-A */
+ 
+ /* If it is necessary to assign new unofficial EM_* values, please
+    pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+index 86408598a465..eb68b6b3d9e3 100644
+--- a/kexec/arch/arm64/kexec-arm64.c
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -7,6 +7,7 @@
+ #include <assert.h>
+ #include <ctype.h>
+ #include <dirent.h>
++#include <elf.h>
+ #include <errno.h>
+ #include <getopt.h>
+ #include <inttypes.h>
+@@ -19,8 +20,6 @@
+ 
+ #include <sys/stat.h>
+ 
+-#include <linux/elf.h>
+-
+ #include "dt-ops.h"
+ #include "kexec.h"
+ #include "crashdump.h"
+diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
+index 13dc5e2724d9..8b336054a6ab 100644
+--- a/kexec/arch/arm64/kexec-elf-arm64.c
++++ b/kexec/arch/arm64/kexec-elf-arm64.c
+@@ -5,12 +5,11 @@
+ #define _GNU_SOURCE
+ 
+ #include <assert.h>
++#include <elf.h>
+ #include <errno.h>
+ #include <getopt.h>
+ #include <libfdt.h>
+ 
+-#include <linux/elf.h>
+-
+ #include "dt-ops.h"
+ #include "crashdump-arm64.h"
+ #include "kexec-arm64.h"
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-kdump-Add-support-for-binary-image.patch b/SOURCES/kexec-tools-2.0.8-arm64-kdump-Add-support-for-binary-image.patch
new file mode 100644
index 0000000..8eb064b
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-kdump-Add-support-for-binary-image.patch
@@ -0,0 +1,70 @@
+From 249821e20306fbafff9094a4e02c82b189ea0676 Mon Sep 17 00:00:00 2001
+Message-Id: <249821e20306fbafff9094a4e02c82b189ea0676.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: Pratyush Anand <panand@redhat.com>
+Date: Tue, 21 Apr 2015 18:23:38 +0530
+Subject: [PATCH 14/17] arm64: kdump: Add support for binary image
+
+This patch adds support to use binary image ie arch/arm64/boot/Image
+with kdump.
+
+Signed-off-by: Pratyush Anand <panand@redhat.com>
+---
+ kexec/arch/arm64/kexec-image-arm64.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/kexec/arch/arm64/kexec-image-arm64.c b/kexec/arch/arm64/kexec-image-arm64.c
+index c577b96d5e31..6f8a6590639a 100644
+--- a/kexec/arch/arm64/kexec-image-arm64.c
++++ b/kexec/arch/arm64/kexec-image-arm64.c
+@@ -10,6 +10,7 @@
+ #include <libfdt.h>
+ #include <stdlib.h>
+ 
++#include "crashdump-arm64.h"
+ #include "dt-ops.h"
+ #include "image-header.h"
+ #include "kexec-arm64.h"
+@@ -97,13 +98,23 @@ int image_arm64_load(int argc, char **argv, const char *kernel_buf,
+ 
+ 	arm64_mem.page_offset = get_kernel_page_offset();
+ 
+-	result = parse_iomem_single("Kernel code\n", &start, NULL);
++	if (info->kexec_flags & KEXEC_ON_CRASH) {
++		result = load_crashdump_segments(info, &header_option);
+ 
+-	if (result) {
+-		fprintf(stderr, "kexec: Could not get kernel code address.\n");
+-		return -1;
++		if (result) {
++			fprintf(stderr, "kexec: load crashdump segments failed.\n");
++			return -1;
++		}
++		start = crash_reserved_mem.start;
++	} else {
++		result = parse_iomem_single("Kernel code\n", &start, NULL);
++
++		if (result) {
++			fprintf(stderr, "kexec: Could not get kernel code address.\n");
++			return -1;
++		}
++		start -= arm64_mem.text_offset;
+ 	}
+-	start -= arm64_mem.text_offset;
+ 
+ 	/* Add kernel */
+ 	add_segment_phys_virt(info, kernel_buf, kernel_size,
+@@ -112,7 +123,8 @@ int image_arm64_load(int argc, char **argv, const char *kernel_buf,
+ 
+ 	info->entry = (void *)start + arm64_mem.text_offset;
+ 
+-	result = arm64_load_other_segments(info, (unsigned long)info->entry);
++	result = arm64_load_other_segments(info, (unsigned long)info->entry,
++		header_option);
+ 
+ 	if (header_option)
+ 		free(header_option);
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-kdump-append-kdump-specific-parameter-to-comma.patch b/SOURCES/kexec-tools-2.0.8-arm64-kdump-append-kdump-specific-parameter-to-comma.patch
new file mode 100644
index 0000000..a1b5609
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-kdump-append-kdump-specific-parameter-to-comma.patch
@@ -0,0 +1,78 @@
+From dd86e7cedfc0509df5dd7f824611d59cf7e9f007 Mon Sep 17 00:00:00 2001
+Message-Id: <dd86e7cedfc0509df5dd7f824611d59cf7e9f007.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: AKASHI Takahiro <takahiro.akashi@linaro.org>
+Date: Tue, 24 Feb 2015 16:46:35 +0900
+Subject: [PATCH 09/17] arm64: kdump: append kdump-specific parameter to
+ command line
+
+---
+ kexec/arch/arm64/kexec-arm64.c     | 9 +++++++--
+ kexec/arch/arm64/kexec-arm64.h     | 2 +-
+ kexec/arch/arm64/kexec-elf-arm64.c | 3 ++-
+ 3 files changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+index e83e83bdd6db..173631c66951 100644
+--- a/kexec/arch/arm64/kexec-arm64.c
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -586,7 +586,7 @@ static uint64_t read_sink(const char *command_line)
+  */
+ 
+ int arm64_load_other_segments(struct kexec_info *info,
+-	unsigned long kernel_entry)
++	unsigned long kernel_entry, char *option)
+ {
+ 	int result;
+ 	struct mem_ehdr ehdr;
+@@ -599,14 +599,19 @@ int arm64_load_other_segments(struct kexec_info *info,
+ 	struct dtb dtb_2 = {.name = "dtb_2"};
+ 	char command_line[COMMAND_LINE_SIZE] = "";
+ 
++	dbgprintf("%s:%d: add '%s' to command line\n", __func__, __LINE__,
++		option);
++
+ 	if (arm64_opts.command_line) {
+ 		strncpy(command_line, arm64_opts.command_line,
+ 			sizeof(command_line));
+ 		command_line[sizeof(command_line) - 1] = 0;
+ 	}
+ 
+-	purgatory_sink = read_sink(command_line);
++	if (option && option[0])
++		strcat(command_line, option);
+ 
++	purgatory_sink = read_sink(command_line);
+ 	dbgprintf("%s:%d: purgatory sink: 0x%" PRIx64 "\n", __func__, __LINE__,
+ 		purgatory_sink);
+ 
+diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
+index 7f0ca13fec11..7e4d0568bd01 100644
+--- a/kexec/arch/arm64/kexec-arm64.h
++++ b/kexec/arch/arm64/kexec-arm64.h
+@@ -48,6 +48,6 @@ extern struct arm64_mem arm64_mem;
+ 
+ int arm64_process_image_header(const struct arm64_image_header *h);
+ int arm64_load_other_segments(struct kexec_info *info,
+-	unsigned long kernel_entry);
++	unsigned long kernel_entry, char *option);
+ 
+ #endif
+diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
+index 903602985eb4..f5ecda825278 100644
+--- a/kexec/arch/arm64/kexec-elf-arm64.c
++++ b/kexec/arch/arm64/kexec-elf-arm64.c
+@@ -123,7 +123,8 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+ 	dbgprintf("%s: e_entry:     %016llx -> %016lx\n", __func__,
+ 		ehdr.e_entry, virt_to_phys(ehdr.e_entry));
+ 
+-	result = arm64_load_other_segments(info, (unsigned long)info->entry);
++	result = arm64_load_other_segments(info, (unsigned long)info->entry,
++		header_option);
+ exit:
+ 	free_elf_info(&ehdr);
+ 	if (header_option)
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-kdump-copy-dtb-file-into-crash-kernel-memory.patch b/SOURCES/kexec-tools-2.0.8-arm64-kdump-copy-dtb-file-into-crash-kernel-memory.patch
new file mode 100644
index 0000000..516aa71
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-kdump-copy-dtb-file-into-crash-kernel-memory.patch
@@ -0,0 +1,68 @@
+From 55cd3491542a0d696451611a4cae38db78f964dd Mon Sep 17 00:00:00 2001
+Message-Id: <55cd3491542a0d696451611a4cae38db78f964dd.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: AKASHI Takahiro <takahiro.akashi@linaro.org>
+Date: Tue, 24 Feb 2015 15:48:29 +0900
+Subject: [PATCH 10/17] arm64: kdump: copy dtb file into crash kernel memory
+
+---
+ kexec/arch/arm64/crashdump-arm64.c |  6 ++++++
+ kexec/arch/arm64/crashdump-arm64.h |  1 +
+ kexec/arch/arm64/kexec-arm64.c     | 15 +++++++++------
+ 3 files changed, 16 insertions(+), 6 deletions(-)
+
+diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
+index ec83cf0c0f38..80f5985c5d85 100644
+--- a/kexec/arch/arm64/crashdump-arm64.c
++++ b/kexec/arch/arm64/crashdump-arm64.c
+@@ -306,3 +306,9 @@ void set_crash_entry(struct mem_ehdr *ehdr, struct kexec_info *info)
+ {
+ 	info->entry = (void *)crash_reserved_mem.start + arm64_mem.text_offset;
+ }
++
++off_t locate_dtb_in_crashmem(struct kexec_info *info, off_t dtb_size)
++{
++	return locate_hole(info, dtb_size, 128UL * 1024,
++		crash_reserved_mem.start, crash_reserved_mem.end, -1);
++}
+diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
+index 3f8b38350841..d4fd3f2288c9 100644
+--- a/kexec/arch/arm64/crashdump-arm64.h
++++ b/kexec/arch/arm64/crashdump-arm64.h
+@@ -21,5 +21,6 @@ extern struct memory_ranges usablemem_rgns;
+ int load_crashdump_segments(struct kexec_info *info, char **option);
+ void modify_ehdr_for_crashmem(struct mem_ehdr *ehdr);
+ void set_crash_entry(struct mem_ehdr *ehdr, struct kexec_info *info);
++off_t locate_dtb_in_crashmem(struct kexec_info *info, off_t dtb_size);
+ 
+ #endif
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+index 173631c66951..190037c75186 100644
+--- a/kexec/arch/arm64/kexec-arm64.c
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -650,12 +650,15 @@ int arm64_load_other_segments(struct kexec_info *info,
+ 
+ 	dtb_max = dtb_2.size + 2 * 1024;
+ 
+-	dtb_base = locate_hole(info, dtb_max, 128UL * 1024,
+-		arm64_mem.memstart + arm64_mem.text_offset
+-			+ arm64_mem.image_size,
+-		_ALIGN_UP(arm64_mem.memstart + arm64_mem.text_offset,
+-			512UL * 1024 * 1024),
+-		1);
++	if (info->kexec_flags & KEXEC_ON_CRASH)
++		dtb_base = locate_dtb_in_crashmem(info, dtb_max);
++	else
++		dtb_base = locate_hole(info, dtb_max, 128UL * 1024,
++			arm64_mem.memstart + arm64_mem.text_offset
++				+ arm64_mem.image_size,
++			_ALIGN_UP(arm64_mem.memstart + arm64_mem.text_offset,
++				512UL * 1024 * 1024),
++			1);
+ 
+ 	dbgprintf("dtb:    base %lx, size %lxh (%ld)\n", dtb_base, dtb_2.size,
+ 		dtb_2.size);
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-kdump-create-elf-core-header.patch b/SOURCES/kexec-tools-2.0.8-arm64-kdump-create-elf-core-header.patch
new file mode 100644
index 0000000..31d3dbe
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-kdump-create-elf-core-header.patch
@@ -0,0 +1,468 @@
+From 9cd9f0ab98ce6ddbdbb9a045ed2887e0dd857afe Mon Sep 17 00:00:00 2001
+Message-Id: <9cd9f0ab98ce6ddbdbb9a045ed2887e0dd857afe.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: AKASHI Takahiro <takahiro.akashi@linaro.org>
+Date: Tue, 17 Feb 2015 16:06:55 +0900
+Subject: [PATCH 08/17] arm64: kdump: create elf core header
+
+---
+ kexec/arch/arm64/crashdump-arm64.c | 295 ++++++++++++++++++++++++++++++++++++-
+ kexec/arch/arm64/crashdump-arm64.h |  17 ++-
+ kexec/arch/arm64/kexec-arm64.c     |   4 +-
+ kexec/arch/arm64/kexec-elf-arm64.c |  31 +++-
+ 4 files changed, 332 insertions(+), 15 deletions(-)
+
+diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
+index d2272c8124d0..ec83cf0c0f38 100644
+--- a/kexec/arch/arm64/crashdump-arm64.c
++++ b/kexec/arch/arm64/crashdump-arm64.c
+@@ -1,11 +1,28 @@
+ /*
+- * ARM64 crashdump.
++ * crashdump for arm64
++ *
++ * Copyright (C) Nokia Corporation, 2010.
++ * Author: Mika Westerberg
++ *
++ * Based on x86 implementation
++ * Copyright (C) IBM Corporation, 2005. All rights reserved
++ *
++ * Copyright (c) 2014 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
++#define _GNU_SOURCE /* for asprintf */
+ 
++#include <assert.h>
++#include <elf.h>
+ #include <errno.h>
+-#include <linux/elf.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
+ 
+ #include "kexec.h"
+ #include "crashdump.h"
+@@ -13,9 +30,279 @@
+ #include "kexec-arm64.h"
+ #include "kexec-elf.h"
+ 
+-struct memory_ranges usablemem_rgns = {};
++
++/*
++ * Used to save various memory ranges/regions needed for the captured
++ * kernel to boot. (like memmap= option in other archs)
++ */
++static struct memory_range crash_memory_ranges[CRASH_MAX_MEMORY_RANGES];
++struct memory_ranges crashmem_rgns = {
++	.size = 0,
++	.ranges = crash_memory_ranges,
++};
++
++/* memory range reserved for crashkernel */
++struct memory_range crash_reserved_mem;
++struct memory_ranges usablemem_rgns = {
++	.size = 0,
++	.ranges = &crash_reserved_mem,
++};
++
++static struct crash_elf_info elf_info = {
++	.class		= ELFCLASS64,
++#if (__BYTE_ORDER == __LITTLE_ENDIAN)
++	.data		= ELFDATA2LSB,
++#else
++	.data		= ELFDATA2MSB,
++#endif
++	.machine	= EM_AARCH64,
++};
+ 
+ int is_crashkernel_mem_reserved(void)
+ {
++	uint64_t start, end;
++
++	if (parse_iomem_single("Crash kernel\n", &start, &end) == 0)
++		return start != end;
++
++	return 0;
++}
++
++/*
++ * crash_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: @crash_memory_ranges and @crash_reserved_mem. Number of memory
++ * regions is placed in @crash_memory_nr_ranges.
++ */
++
++static int crash_range_callback(void *UNUSED(data), int UNUSED(nr),
++				char *str, unsigned long long base,
++				unsigned long long length)
++{
++	struct memory_range *range;
++
++	assert(arm64_mem.memstart);
++
++	if (crashmem_rgns.size >= CRASH_MAX_MEMORY_RANGES)
++		return 1;
++
++	range = crashmem_rgns.ranges + crashmem_rgns.size;
++
++	if (strncmp(str, "System RAM\n", 11) == 0) {
++		range->start = base;
++		range->end = base + length - 1;
++		range->type = RANGE_RAM;
++		crashmem_rgns.size++;
++	} else if (strncmp(str, "Crash kernel\n", 13) == 0) {
++		if (base < arm64_mem.memstart)
++			base += arm64_mem.memstart;
++		crash_reserved_mem.start = base;
++		crash_reserved_mem.end = base + length - 1;
++		crash_reserved_mem.type = RANGE_RAM;
++		usablemem_rgns.size++;
++	}
++
++	return 0;
++}
++
++/*
++ * crash_exclude_range() - excludes memory region reserved for crashkernel
++ *
++ * Function locates where crashkernel reserved memory is and removes that
++ * region from the available memory regions.
++ */
++static void crash_exclude_range(void)
++{
++	const struct memory_range *range = &crash_reserved_mem;
++	int i;
++
++	for (i = 0; i < crashmem_rgns.size; i++) {
++		struct memory_range *r = crashmem_rgns.ranges + i;
++
++		/*
++		 * We assume that crash area is fully contained in
++		 * some larger memory area.
++		 */
++		if (r->start <= range->start && r->end >= range->end) {
++			struct memory_range *new;
++
++			if (r->start == range->start) {
++				if (r->end == range->end) {
++					memcpy(r, r + 1,
++						sizeof(r)
++						* (crashmem_rgns.size - i - 1));
++					crashmem_rgns.size--;
++				} else {
++					r->start = range->end + 1;
++				}
++				break;
++			}
++			if (r->end == range->end) {
++				r->end = range->start - 1;
++				break;
++			}
++
++			/*
++			 * Let's split this area into 2 smaller ones and
++			 * remove excluded range from between. First create
++			 * new entry for the remaining area.
++			 */
++			new = crashmem_rgns.ranges + crashmem_rgns.size;
++			new->start = range->end + 1;
++			new->end = r->end;
++			crashmem_rgns.size++;
++			/*
++			 * Next update this area to end before excluded range.
++			 */
++			r->end = range->start - 1;
++			break;
++		}
++	}
++}
++
++/*
++ * crash_get_memory_ranges() - read system physical memory
++ *
++ * Function reads through system physical memory and stores found memory
++ * regions in @crash_memory_ranges. Number of memory regions found is placed
++ * in @crash_memory_nr_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.
++	 */
++	kexec_iomem_for_each_line(NULL, crash_range_callback, NULL);
++
++	if (usablemem_rgns.size != 1) {
++		errno = EINVAL;
++		return -1;
++	}
++
++	/*
++	 * Exclude memory reserved for crashkernel (this may result int
++	 * split memory regions).
++	 */
++	/*
++	 * FIXME:
++	 * Do we have to check crashkernel is within main memory?
++	 */
++	crash_exclude_range();
++
++	return 0;
++}
++
++/*
++ * range_size - Return range size in MiB.
++ */
++
++static unsigned long range_size(const struct memory_range *r)
++{
++	return (r->end - r->start + 1) >> 20;
++}
++
++static void dump_crash_ranges(void)
++{
++	int i;
++
++	if (!kexec_debug)
++		return;
++
++	dbgprintf("%s: kernel: %016llx - %016llx (%ld MiB)\n", __func__,
++		  crash_reserved_mem.start, crash_reserved_mem.end,
++		  range_size(&crash_reserved_mem));
++
++	for (i = 0; i < crashmem_rgns.size; i++) {
++		struct memory_range *r = crashmem_rgns.ranges + i;
++		dbgprintf("%s: RAM:    %016llx - %016llx (%ld MiB)\n", __func__,
++			  r->start, r->end, range_size(r));
++	}
++}
++
++/*
++ * load_crashdump_segments() - create elf core header for /proc/vmcore
++ * @info: kexec info structure
++ * @option: To be appended to kernel command line
++ *
++ * This function loads additional segments which are needed for the dump
++ * capture kernel. It also updates kernel command line passed in
++ * @command_line_extra to have the correct parameters for the dump capture
++ * kernel.
++ *
++ * Return %0 in case of success and %-1 in case of error.
++ */
++
++int load_crashdump_segments(struct kexec_info *info, char **option)
++{
++	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 crashdump kernel during panic.
++	 */
++
++	err = crash_get_memory_ranges();
++
++	if (err)
++		return err;
++
++	dump_crash_ranges();
++
++	elf_info.page_offset = arm64_mem.page_offset;
++
++	err = crash_create_elf64_headers(info, &elf_info, crashmem_rgns.ranges,
++		crashmem_rgns.size, &buf, &bufsz, ELF_CORE_HEADER_ALIGN);
++
++	if (err)
++		return err;
++
++	/*
++	 * FIXME: check if we need 128KB alignment here as stated in arm.
++	 */
++	elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 0,
++		crash_reserved_mem.start, crash_reserved_mem.end,
++		-1, 0);
++
++	err = asprintf(option, " elfcorehdr=%#lx@%#lx", bufsz, elfcorehdr);
++
++	if (err == -1)
++		return err;
++
++	dbgprintf("%s:%s\n", __func__, *option);
++
+ 	return 0;
+ }
++
++void modify_ehdr_for_crashmem(struct mem_ehdr *ehdr)
++{
++	struct mem_phdr *phdr;
++	int i;
++
++	ehdr->e_entry += 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.memstart + crash_reserved_mem.start);
++	}
++}
++
++void set_crash_entry(struct mem_ehdr *ehdr, struct kexec_info *info)
++{
++	info->entry = (void *)crash_reserved_mem.start + arm64_mem.text_offset;
++}
+diff --git a/kexec/arch/arm64/crashdump-arm64.h b/kexec/arch/arm64/crashdump-arm64.h
+index f33c7a25b454..3f8b38350841 100644
+--- a/kexec/arch/arm64/crashdump-arm64.h
++++ b/kexec/arch/arm64/crashdump-arm64.h
+@@ -1,12 +1,25 @@
+ /*
+- * ARM64 crashdump.
++ * crashdump for arm64
++ *
++ * Copyright (c) 2014 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;
+ 
++int load_crashdump_segments(struct kexec_info *info, char **option);
++void modify_ehdr_for_crashmem(struct mem_ehdr *ehdr);
++void set_crash_entry(struct mem_ehdr *ehdr, struct kexec_info *info);
++
+ #endif
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+index eb68b6b3d9e3..e83e83bdd6db 100644
+--- a/kexec/arch/arm64/kexec-arm64.c
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -758,7 +758,7 @@ unsigned long phys_to_virt(struct crash_elf_info *UNUSED(elf_info),
+ 	v = p - arm64_mem.memstart + arm64_mem.page_offset;
+ 
+ 	dbgprintf("%s: %016lx -> %016lx\n", __func__, p, v);
+-	return p;
++	return v;
+ }
+ 
+ void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
+@@ -924,7 +924,7 @@ static int get_memory_ranges_iomem(struct memory_range *array,
+ 
+ 		r.type = RANGE_RAM;
+ 
+-		dbgprintf("%s:%d: RAM:  %016llx - %016llx : %s", __func__,
++		dbgprintf("%s:%d: RAM: %016llx - %016llx : %s", __func__,
+ 			__LINE__, r.start, r.end, str);
+ 
+ 		array[(*count)++] = r;
+diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c
+index 8b336054a6ab..903602985eb4 100644
+--- a/kexec/arch/arm64/kexec-elf-arm64.c
++++ b/kexec/arch/arm64/kexec-elf-arm64.c
+@@ -9,9 +9,10 @@
+ #include <errno.h>
+ #include <getopt.h>
+ #include <libfdt.h>
++#include <stdlib.h>
+ 
+-#include "dt-ops.h"
+ #include "crashdump-arm64.h"
++#include "dt-ops.h"
+ #include "kexec-arm64.h"
+ #include "fs2dt.h"
+ #include "kexec-syscall.h"
+@@ -45,16 +46,13 @@ on_exit:
+ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+ 	off_t kernel_size, struct kexec_info *info)
+ {
++	char *header_option = NULL;
+ 	int result;
+ 	struct mem_ehdr ehdr;
+ 	bool found_header;
+ 	int i;
+ 
+-	if (info->kexec_flags & KEXEC_ON_CRASH) {
+-		fprintf(stderr, "kexec: kdump not yet supported on arm64\n");
+-		return -EINVAL;
+-	}
+-
++	/* Parse the Elf file */
+ 	result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0);
+ 
+ 	if (result < 0) {
+@@ -94,6 +92,18 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+ 		goto exit;
+ 	}
+ 
++	if (info->kexec_flags & KEXEC_ON_CRASH) {
++		result = load_crashdump_segments(info, &header_option);
++
++		if (result) {
++			fprintf(stderr, "kexec: creating eflcorehdr failed.\n");
++			goto exit;
++		}
++	}
++
++	if (info->kexec_flags & KEXEC_ON_CRASH)
++		modify_ehdr_for_crashmem(&ehdr);
++
+ 	result = elf_exec_load(&ehdr, info);
+ 
+ 	if (result) {
+@@ -101,6 +111,11 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+ 		goto exit;
+ 	}
+ 
++	if (info->kexec_flags & KEXEC_ON_CRASH)
++		set_crash_entry(&ehdr, info);
++	else
++		info->entry = (void *)virt_to_phys(ehdr.e_entry);
++
+ 	dbgprintf("%s: text_offset: %016lx\n", __func__, arm64_mem.text_offset);
+ 	dbgprintf("%s: image_size:  %016lx\n", __func__, arm64_mem.image_size);
+ 	dbgprintf("%s: page_offset: %016lx\n", __func__, arm64_mem.page_offset);
+@@ -108,9 +123,11 @@ int elf_arm64_load(int argc, char **argv, const char *kernel_buf,
+ 	dbgprintf("%s: e_entry:     %016llx -> %016lx\n", __func__,
+ 		ehdr.e_entry, virt_to_phys(ehdr.e_entry));
+ 
+-	result = arm64_load_other_segments(info, virt_to_phys(ehdr.e_entry));
++	result = arm64_load_other_segments(info, (unsigned long)info->entry);
+ exit:
+ 	free_elf_info(&ehdr);
++	if (header_option)
++		free(header_option);
+ 	return result;
+ }
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-pass-mem-parameter-to-a-crash-dump-kernel.patch b/SOURCES/kexec-tools-2.0.8-arm64-pass-mem-parameter-to-a-crash-dump-kernel.patch
new file mode 100644
index 0000000..b21731c
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-pass-mem-parameter-to-a-crash-dump-kernel.patch
@@ -0,0 +1,30 @@
+From dbb9a351c5bd0c51b959a9ffc19859bee1b82008 Mon Sep 17 00:00:00 2001
+Message-Id: <dbb9a351c5bd0c51b959a9ffc19859bee1b82008.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: AKASHI Takahiro <takahiro.akashi@linaro.org>
+Date: Thu, 26 Mar 2015 19:13:44 +0900
+Subject: [PATCH 11/17] arm64: pass "mem=" parameter to a crash dump kernel
+
+---
+ kexec/arch/arm64/crashdump-arm64.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/kexec/arch/arm64/crashdump-arm64.c b/kexec/arch/arm64/crashdump-arm64.c
+index 80f5985c5d85..04958418ae82 100644
+--- a/kexec/arch/arm64/crashdump-arm64.c
++++ b/kexec/arch/arm64/crashdump-arm64.c
+@@ -276,7 +276,9 @@ int load_crashdump_segments(struct kexec_info *info, char **option)
+ 		crash_reserved_mem.start, crash_reserved_mem.end,
+ 		-1, 0);
+ 
+-	err = asprintf(option, " elfcorehdr=%#lx@%#lx", bufsz, elfcorehdr);
++	err = asprintf(option, " elfcorehdr=%#lx@%#lx mem=%#llx",
++			bufsz, elfcorehdr,
++			crash_reserved_mem.end - crash_reserved_mem.start + 1);
+ 
+ 	if (err == -1)
+ 		return err;
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-remove-restriction-on-the-segments-order.patch b/SOURCES/kexec-tools-2.0.8-arm64-remove-restriction-on-the-segments-order.patch
new file mode 100644
index 0000000..0d850fe
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-remove-restriction-on-the-segments-order.patch
@@ -0,0 +1,123 @@
+From 97905e5e71d417e8bbbfa3c42d559a464a1570da Mon Sep 17 00:00:00 2001
+Message-Id: <97905e5e71d417e8bbbfa3c42d559a464a1570da.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: AKASHI Takahiro <takahiro.akashi@linaro.org>
+Date: Wed, 22 Apr 2015 11:21:05 +0900
+Subject: [PATCH 13/17] arm64: remove restriction on the segments order
+
+Done by changing locate_hole() to add_buffer_phys_virt() in
+load_other_segments() since locate_hole() assumes that the segments in
+struct info be sorted properly.
+This also simplifies the difference between kexec case and kdump case.
+---
+ kexec/arch/arm64/kexec-arm64.c | 57 +++++++++++++++---------------------------
+ 1 file changed, 20 insertions(+), 37 deletions(-)
+
+diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
+index 190037c75186..d884c7c1707d 100644
+--- a/kexec/arch/arm64/kexec-arm64.c
++++ b/kexec/arch/arm64/kexec-arm64.c
+@@ -590,11 +590,10 @@ int arm64_load_other_segments(struct kexec_info *info,
+ {
+ 	int result;
+ 	struct mem_ehdr ehdr;
+-	unsigned long dtb_max;
+ 	unsigned long dtb_base;
++	unsigned long hole_min, hole_max;
+ 	char *initrd_buf = NULL;
+ 	uint64_t purgatory_sink;
+-	unsigned long purgatory_base;
+ 	struct dtb dtb_1 = {.name = "dtb_1"};
+ 	struct dtb dtb_2 = {.name = "dtb_2"};
+ 	char command_line[COMMAND_LINE_SIZE] = "";
+@@ -648,27 +647,15 @@ int arm64_load_other_segments(struct kexec_info *info,
+ 	 * to the DTB size for any DTB growth.
+ 	 */
+ 
+-	dtb_max = dtb_2.size + 2 * 1024;
+-
+-	if (info->kexec_flags & KEXEC_ON_CRASH)
+-		dtb_base = locate_dtb_in_crashmem(info, dtb_max);
+-	else
+-		dtb_base = locate_hole(info, dtb_max, 128UL * 1024,
+-			arm64_mem.memstart + arm64_mem.text_offset
+-				+ arm64_mem.image_size,
+-			_ALIGN_UP(arm64_mem.memstart + arm64_mem.text_offset,
+-				512UL * 1024 * 1024),
+-			1);
+-
+-	dbgprintf("dtb:    base %lx, size %lxh (%ld)\n", dtb_base, dtb_2.size,
+-		dtb_2.size);
+-
+-	if (dtb_base == ULONG_MAX)
+-		return -ENOMEM;
+-
+-	purgatory_base = dtb_base + dtb_2.size;
+-	initrd_base = 0;
+-	initrd_size = 0;
++	if (info->kexec_flags & KEXEC_ON_CRASH) {
++		hole_min = crash_reserved_mem.start + arm64_mem.text_offset
++				+ arm64_mem.image_size;
++		hole_max = crash_reserved_mem.end;
++	} else {
++		hole_min = arm64_mem.memstart + arm64_mem.text_offset
++				+ arm64_mem.image_size;
++		hole_max = ULONG_MAX;
++	}
+ 
+ 	if (arm64_opts.initrd) {
+ 		initrd_buf = slurp_file(arm64_opts.initrd, &initrd_size);
+@@ -679,8 +666,9 @@ int arm64_load_other_segments(struct kexec_info *info,
+ 			/* Put the initrd after the DTB with an alignment of
+ 			 * page size. */
+ 
+-			initrd_base = locate_hole(info, initrd_size, 0,
+-				dtb_base + dtb_max, -1, 1);
++			initrd_base = add_buffer_phys_virt(info, initrd_buf,
++				initrd_size, initrd_size, 0,
++				hole_min, hole_max, 1, 0);
+ 
+ 			dbgprintf("initrd: base %lx, size %lxh (%ld)\n",
+ 				initrd_base, initrd_size, initrd_size);
+@@ -694,22 +682,17 @@ int arm64_load_other_segments(struct kexec_info *info,
+ 
+ 			if (result)
+ 				return result;
+-
+-			purgatory_base = initrd_base + initrd_size;
+ 		}
+ 	}
+ 
+-	if (dtb_2.size > dtb_max) {
+-		fprintf(stderr, "%s: Error: Too many DTB mods.\n", __func__);
+-		return -EINVAL;
+-	}
++	dtb_base = add_buffer_phys_virt(info, dtb_2.buf, dtb_2.size, dtb_2.size,
++			128UL * 1024, hole_min, hole_max, 1, 0);
+ 
+-	add_segment_phys_virt(info, dtb_2.buf, dtb_2.size, dtb_base,
+-		dtb_2.size, 0);
++	dbgprintf("dtb:    base %lx, size %lxh (%ld)\n", dtb_base, dtb_2.size,
++		dtb_2.size);
+ 
+-	if (arm64_opts.initrd)
+-		add_segment_phys_virt(info, initrd_buf, initrd_size,
+-				initrd_base, initrd_size, 0);
++	if (dtb_base == ULONG_MAX)
++		return -ENOMEM;
+ 
+ 	if (arm64_opts.lite)
+ 		info->entry = (void *)kernel_entry;
+@@ -724,7 +707,7 @@ int arm64_load_other_segments(struct kexec_info *info,
+ 		}
+ 
+ 		elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size,
+-			purgatory_base, ULONG_MAX, 1, 0);
++			hole_min, hole_max, 1, 0);
+ 
+ 		info->entry = (void *)elf_rel_get_addr(&info->rhdr,
+ 			"purgatory_start");
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-arm64-wait-for-transmit-completion-before-next-chara.patch b/SOURCES/kexec-tools-2.0.8-arm64-wait-for-transmit-completion-before-next-chara.patch
new file mode 100644
index 0000000..400a868
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-arm64-wait-for-transmit-completion-before-next-chara.patch
@@ -0,0 +1,64 @@
+From fc60d1ebadfba9a4344969507d8bd9de43c5c7e8 Mon Sep 17 00:00:00 2001
+Message-Id: <fc60d1ebadfba9a4344969507d8bd9de43c5c7e8.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: Pratyush Anand <panand@redhat.com>
+Date: Thu, 16 Apr 2015 14:00:03 +0530
+Subject: [PATCH 15/17] arm64: wait for transmit completion before next
+ character transmission
+
+Previous transmission must be completed before next character to be
+transmitted, otherwise TX buffer may saturate and we will not see all
+the characters on screen.
+
+Signed-off-by: Pratyush Anand <panand@redhat.com>
+---
+ purgatory/arch/arm64/purgatory-arm64.c | 24 +++++++++++++++++++++++-
+ 1 file changed, 23 insertions(+), 1 deletion(-)
+
+diff --git a/purgatory/arch/arm64/purgatory-arm64.c b/purgatory/arch/arm64/purgatory-arm64.c
+index 25960c30bd05..3a1c9243bfa2 100644
+--- a/purgatory/arch/arm64/purgatory-arm64.c
++++ b/purgatory/arch/arm64/purgatory-arm64.c
+@@ -11,15 +11,37 @@ extern uint32_t *arm64_sink;
+ extern void (*arm64_kernel_entry)(uint64_t);
+ extern uint64_t arm64_dtb_addr;
+ 
++static void wait_for_xmit_complete(void)
++{
++	volatile uint32_t status;
++	volatile uint32_t *status_reg;
++
++	/*
++	 * Since most of the UART with ARM platform has LSR register at
++	 * offset 0x14 and should have value as 0x60 for TX empty, so we
++	 * have hardcoded these values. Can modify in future if need
++	 * arises.
++	 */
++	status_reg = (volatile uint32_t *)((uint64_t)arm64_sink + 0x14);
++	while (1) {
++		status = *status_reg;
++		if ((status & 0x60) == 0x60)
++			break;
++	}
++}
++
+ void putchar(int ch)
+ {
+ 	if (!arm64_sink)
+ 		return;
+ 
++	wait_for_xmit_complete();
+ 	*arm64_sink = ch;
+ 
+-	if (ch == '\n')
++	if (ch == '\n') {
++		wait_for_xmit_complete();
+ 		*arm64_sink = '\r';
++	}
+ }
+ 
+ void setup_arch(void)
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-bugfix-calc-correct-end-address-of-memory-ranges-in-.patch b/SOURCES/kexec-tools-2.0.8-bugfix-calc-correct-end-address-of-memory-ranges-in-.patch
new file mode 100644
index 0000000..b3d5ef6
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-bugfix-calc-correct-end-address-of-memory-ranges-in-.patch
@@ -0,0 +1,41 @@
+From 0ed5f4fb8dfd33bc52c8dbe15c61285d50c769b2 Mon Sep 17 00:00:00 2001
+Message-Id: <0ed5f4fb8dfd33bc52c8dbe15c61285d50c769b2.1431592766.git.panand@redhat.com>
+In-Reply-To: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+References: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: AKASHI Takahiro <takahiro.akashi@linaro.org>
+Date: Fri, 22 Aug 2014 13:48:52 +0900
+Subject: [PATCH 06/17] (bugfix) calc correct end address of memory ranges in
+ device tree
+
+The end address of "reg" attribute in device tree's memory should be
+inclusive.
+---
+ kexec/fs2dt.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/kexec/fs2dt.c b/kexec/fs2dt.c
+index 1e5f074da8b2..3ba217873f4f 100644
+--- a/kexec/fs2dt.c
++++ b/kexec/fs2dt.c
+@@ -234,7 +234,8 @@ static void add_dyn_reconf_usable_mem_property__(int fd)
+ 						    ranges_size*8);
+ 				}
+ 				ranges[rlen++] = cpu_to_be64(loc_base);
+-				ranges[rlen++] = cpu_to_be64(loc_end - loc_base);
++				ranges[rlen++] = cpu_to_be64(loc_end
++								- loc_base + 1);
+ 				rngs_cnt++;
+ 			}
+ 		}
+@@ -348,7 +349,7 @@ static void add_usable_mem_property(int fd, size_t len)
+ 					    ranges_size*sizeof(*ranges));
+ 			}
+ 			ranges[rlen++] = cpu_to_be64(loc_base);
+-			ranges[rlen++] = cpu_to_be64(loc_end - loc_base);
++			ranges[rlen++] = cpu_to_be64(loc_end - loc_base + 1);
+ 		}
+ 	}
+ 
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-kexec-Add-common-device-tree-routines.patch b/SOURCES/kexec-tools-2.0.8-kexec-Add-common-device-tree-routines.patch
new file mode 100644
index 0000000..b2630fc
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-kexec-Add-common-device-tree-routines.patch
@@ -0,0 +1,194 @@
+From 1fb6841aa15407dbf371589d7abca7bc2d35815c Mon Sep 17 00:00:00 2001
+Message-Id: <1fb6841aa15407dbf371589d7abca7bc2d35815c.1431592766.git.panand@redhat.com>
+From: Geoff Levand <geoff@infradead.org>
+Date: Fri, 17 Apr 2015 10:54:55 -0700
+Subject: [PATCH 01/17] kexec: Add common device tree routines
+
+Signed-off-by: Geoff Levand <geoff@infradead.org>
+---
+ kexec/Makefile |   4 ++
+ kexec/dt-ops.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ kexec/dt-ops.h |  13 ++++++
+ 3 files changed, 153 insertions(+)
+ create mode 100644 kexec/dt-ops.c
+ create mode 100644 kexec/dt-ops.h
+
+diff --git a/kexec/Makefile b/kexec/Makefile
+index a758b4aae13a..6937a4dbb38b 100644
+--- a/kexec/Makefile
++++ b/kexec/Makefile
+@@ -69,6 +69,10 @@ dist				+= kexec/fs2dt.c kexec/fs2dt.h
+ $(ARCH)_FS2DT			=
+ KEXEC_SRCS			+= $($(ARCH)_FS2DT)
+ 
++dist				+= kexec/dt-ops.c kexec/dt-ops.h
++$(ARCH)_DT_OPS		=
++KEXEC_SRCS			+= $($(ARCH)_DT_OPS)
++
+ include $(srcdir)/kexec/arch/alpha/Makefile
+ include $(srcdir)/kexec/arch/arm/Makefile
+ include $(srcdir)/kexec/arch/i386/Makefile
+diff --git a/kexec/dt-ops.c b/kexec/dt-ops.c
+new file mode 100644
+index 000000000000..bbba986cfbb4
+--- /dev/null
++++ b/kexec/dt-ops.c
+@@ -0,0 +1,136 @@
++#include <assert.h>
++#include <errno.h>
++#include <inttypes.h>
++#include <libfdt.h>
++#include <stdio.h>
++#include <stdlib.h>
++
++#include "kexec.h"
++#include "dt-ops.h"
++
++static const char n_chosen[] = "/chosen";
++
++static const char p_bootargs[] = "bootargs";
++static const char p_initrd_start[] = "linux,initrd-start";
++static const char p_initrd_end[] = "linux,initrd-end";
++
++int dtb_set_initrd(char **dtb, off_t *dtb_size, off_t start, off_t end)
++{
++	int result;
++	uint64_t value;
++
++	dbgprintf("%s: start %jd, end %jd, size %jd (%jd KiB)\n",
++		__func__, (intmax_t)start, (intmax_t)end,
++		(intmax_t)(end - start),
++		(intmax_t)(end - start) / 1024);
++
++	value = cpu_to_fdt64(start);
++
++	result = dtb_set_property(dtb, dtb_size, n_chosen, p_initrd_start,
++		&value, sizeof(value));
++
++	if (result)
++		return result;
++
++	value = cpu_to_fdt64(end);
++
++	result = dtb_set_property(dtb, dtb_size, n_chosen, p_initrd_end,
++		&value, sizeof(value));
++
++	if (result) {
++		dtb_delete_property(*dtb, n_chosen, p_initrd_start);
++		return result;
++	}
++
++	return 0;
++}
++
++int dtb_set_bootargs(char **dtb, off_t *dtb_size, const char *command_line)
++{
++	return dtb_set_property(dtb, dtb_size, n_chosen, p_bootargs,
++		command_line, strlen(command_line) + 1);
++}
++
++int dtb_set_property(char **dtb, off_t *dtb_size, const char *node,
++	const char *prop, const void *value, int value_len)
++{
++	int result;
++	int nodeoffset;
++	void *new_dtb;
++	int new_size;
++
++	value_len = FDT_TAGALIGN(value_len);
++
++	new_size = FDT_TAGALIGN(*dtb_size + fdt_node_len(node)
++		+ fdt_prop_len(prop, value_len));
++
++	new_dtb = malloc(new_size);
++
++	if (!new_dtb) {
++		dbgprintf("%s: malloc failed\n", __func__);
++		return -ENOMEM;
++	}
++
++	result = fdt_open_into(*dtb, new_dtb, new_size);
++
++	if (result) {
++		dbgprintf("%s: fdt_open_into failed: %s\n", __func__,
++			fdt_strerror(result));
++		goto on_error;
++	}
++
++	nodeoffset = fdt_path_offset(new_dtb, node);
++	
++	if (nodeoffset == -FDT_ERR_NOTFOUND) {
++		result = fdt_add_subnode(new_dtb, nodeoffset, node);
++
++		if (result) {
++			dbgprintf("%s: fdt_add_subnode failed: %s\n", __func__,
++				fdt_strerror(result));
++			goto on_error;
++		}
++	} else if (nodeoffset < 0) {
++		dbgprintf("%s: fdt_path_offset failed: %s\n", __func__,
++			fdt_strerror(nodeoffset));
++		goto on_error;
++	}
++
++	result = fdt_setprop(new_dtb, nodeoffset, prop, value, value_len);
++
++	if (result) {
++		dbgprintf("%s: fdt_setprop failed: %s\n", __func__,
++			fdt_strerror(result));
++		goto on_error;
++	}
++	
++	free(*dtb);
++
++	*dtb = new_dtb;
++	*dtb_size = new_size;
++
++	return 0;
++
++on_error:
++	free(new_dtb);
++	return result;
++}
++
++int dtb_delete_property(char *dtb, const char *node, const char *prop)
++{
++	int result;
++	int nodeoffset = fdt_path_offset(dtb, node);
++
++	if (nodeoffset < 0) {
++		dbgprintf("%s: fdt_path_offset failed: %s\n", __func__,
++			fdt_strerror(nodeoffset));
++		return nodeoffset;
++	}
++
++	result = fdt_delprop(dtb, nodeoffset, prop);
++
++	if (result)
++		dbgprintf("%s: fdt_delprop failed: %s\n", __func__,
++			fdt_strerror(nodeoffset));
++
++	return result;
++}
+diff --git a/kexec/dt-ops.h b/kexec/dt-ops.h
+new file mode 100644
+index 000000000000..e70d15d8ffbf
+--- /dev/null
++++ b/kexec/dt-ops.h
+@@ -0,0 +1,13 @@
++#if !defined(KEXEC_DT_OPS_H)
++#define KEXEC_DT_OPS_H
++
++#include <sys/types.h>
++
++int dtb_set_initrd(char **dtb, off_t *dtb_size, off_t start, off_t end);
++int dtb_set_bootargs(char **dtb, off_t *dtb_size, const char *command_line);
++int dtb_set_property(char **dtb, off_t *dtb_size, const char *node,
++	const char *prop, const void *value, int value_len);
++
++int dtb_delete_property(char *dtb, const char *node, const char *prop);
++
++#endif
+-- 
+2.1.0
+
diff --git a/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-module-of-calculating-start_pfn-and.patch b/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-module-of-calculating-start_pfn-and.patch
new file mode 100644
index 0000000..c4e7676
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-module-of-calculating-start_pfn-and.patch
@@ -0,0 +1,146 @@
+Return-Path: yishimat@redhat.com
+Received: from zmta04.collab.prod.int.phx2.redhat.com (LHLO
+ zmta04.collab.prod.int.phx2.redhat.com) (10.5.81.11) by
+ zmail24.collab.prod.int.phx2.redhat.com with LMTP; Thu, 2 Jul 2015 01:09:57
+ -0400 (EDT)
+Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23])
+	by zmta04.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 29864DA114;
+	Thu,  2 Jul 2015 01:09:57 -0400 (EDT)
+Received: from [10.3.112.13] ([10.3.112.13])
+	by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t6259s7J004916;
+	Thu, 2 Jul 2015 01:09:55 -0400
+Subject: [RHEL7.2 PATCH resend v3 4/5] Add module of calculating start_pfn and
+ end_pfn in each dumpfile.
+To: kexec-kdump-list@redhat.com
+References: <55929D94.4020500@redhat.com> <5594C62C.3030407@redhat.com>
+Cc: Minfei Huang <mhuang@redhat.com>, bhe@redhat.com, yishimat@redhat.com
+From: Yasuaki Ishimatsu <yishimat@redhat.com>
+Message-ID: <5594C7A1.6020609@redhat.com>
+Date: Thu, 2 Jul 2015 01:09:53 -0400
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101
+ Thunderbird/38.0.1
+MIME-Version: 1.0
+In-Reply-To: <5594C62C.3030407@redhat.com>
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23
+Content-Length: 3398
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1182379
+
+The patch is back ported directory from the following upstream commit:
+
+commit 2b74c02081fa0777c8cfb336adb63d9ccb2b46dd
+Author: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+Date:   Fri Nov 7 09:44:56 2014 +0900
+
+    [PATCH v5 4/5] Add module of calculating start_pfn and end_pfn in each
+
+    When --split is specified in cyclic mode, start_pfn and end_pfn of each
+    will be calculated to make each dumpfile have the same size.
+
+    Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
+    Signed-off-by: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+
+Resolves: rhbz#1182379
+Signed-off-by: Yasuaki Ishimatsu <yishimat@redhat.com>
+
+---
+ makedumpfile-1.5.7/makedumpfile.c |   73 ++++++++++++++++++++++++++++++++++---
+ 1 files changed, 68 insertions(+), 5 deletions(-)
+
+diff --git a/makedumpfile-1.5.7/makedumpfile.c b/makedumpfile-1.5.7/makedumpfile.c
+index 5ffe8e1..c4309af 100644
+--- a/makedumpfile-1.5.7/makedumpfile.c
++++ b/makedumpfile-1.5.7/makedumpfile.c
+@@ -8218,6 +8218,65 @@ out:
+ 		return ret;
+ }
+
++/*
++ * calculate end_pfn of one dumpfile.
++ * try to make every output file have the same size.
++ * splitblock_table is used to reduce calculate time.
++ */
++
++#define CURRENT_SPLITBLOCK_PFN_NUM (*cur_splitblock_num * splitblock->page_per_splitblock)
++mdf_pfn_t
++calculate_end_pfn_by_splitblock(mdf_pfn_t start_pfn,
++				 int *cur_splitblock_num)
++{
++	if (start_pfn >= info->max_mapnr)
++		return info->max_mapnr;
++
++	mdf_pfn_t end_pfn;
++	long long pfn_needed, offset;
++	char *splitblock_value_offset;
++
++	pfn_needed = info->num_dumpable / info->num_dumpfile;
++	offset = *cur_splitblock_num * splitblock->entry_size;
++	splitblock_value_offset = splitblock->table + offset;
++	end_pfn = start_pfn;
++
++	while (*cur_splitblock_num < splitblock->num && pfn_needed > 0) {
++		pfn_needed -= read_from_splitblock_table(splitblock_value_offset);
++		splitblock_value_offset += splitblock->entry_size;
++		++*cur_splitblock_num;
++	}
++
++	end_pfn = CURRENT_SPLITBLOCK_PFN_NUM;
++	if (end_pfn > info->max_mapnr)
++		end_pfn = info->max_mapnr;
++
++	return end_pfn;
++}
++
++/*
++ * calculate start_pfn and end_pfn in each output file.
++ */
++static int setup_splitting_cyclic(void)
++{
++	int i;
++	mdf_pfn_t start_pfn, end_pfn;
++	int cur_splitblock_num = 0;
++	start_pfn = end_pfn = 0;
++
++	for (i = 0; i < info->num_dumpfile - 1; i++) {
++		start_pfn = end_pfn;
++		end_pfn = calculate_end_pfn_by_splitblock(start_pfn,
++							  &cur_splitblock_num);
++		SPLITTING_START_PFN(i) = start_pfn;
++		SPLITTING_END_PFN(i) = end_pfn;
++	}
++	SPLITTING_START_PFN(info->num_dumpfile - 1) = end_pfn;
++	SPLITTING_END_PFN(info->num_dumpfile - 1) = info->max_mapnr;
++
++	return TRUE;
++}
++
+ int
+ setup_splitting(void)
+ {
+@@ -8231,12 +8290,16 @@ setup_splitting(void)
+ 		return FALSE;
+
+ 	if (info->flag_cyclic) {
+-		for (i = 0; i < info->num_dumpfile; i++) {
+-			SPLITTING_START_PFN(i) = divideup(info->max_mapnr, info->num_dumpfile) * i;
+-			SPLITTING_END_PFN(i)   = divideup(info->max_mapnr, info->num_dumpfile) * (i + 1);
++		int ret = FALSE;
++
++		if (!prepare_bitmap2_buffer_cyclic()) {
++			free_bitmap_buffer();
++			return ret;
+ 		}
+-		if (SPLITTING_END_PFN(i-1) > info->max_mapnr)
+-			SPLITTING_END_PFN(i-1) = info->max_mapnr;
++		ret = setup_splitting_cyclic();
++		free_bitmap2_buffer_cyclic();
++
++		return ret;
+         } else {
+ 		initialize_2nd_bitmap(&bitmap2);
+
+-- 
+1.7.1
+
diff --git a/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-module-of-generating-table.patch b/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-module-of-generating-table.patch
new file mode 100644
index 0000000..f6e4115
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-module-of-generating-table.patch
@@ -0,0 +1,219 @@
+Return-Path: yishimat@redhat.com
+Received: from zmta05.collab.prod.int.phx2.redhat.com (LHLO
+ zmta05.collab.prod.int.phx2.redhat.com) (10.5.81.12) by
+ zmail24.collab.prod.int.phx2.redhat.com with LMTP; Thu, 2 Jul 2015 01:08:58
+ -0400 (EDT)
+Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27])
+	by zmta05.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 6922D17C114;
+	Thu,  2 Jul 2015 01:08:58 -0400 (EDT)
+Received: from [10.3.112.13] ([10.3.112.13])
+	by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t6258t32026109;
+	Thu, 2 Jul 2015 01:08:56 -0400
+Subject: [RHEL7.2 PATCH resend v3 3/5] Add module of generating table.
+To: kexec-kdump-list@redhat.com
+References: <55929D94.4020500@redhat.com> <5594C62C.3030407@redhat.com>
+Cc: Minfei Huang <mhuang@redhat.com>, bhe@redhat.com, yishimat@redhat.com
+From: Yasuaki Ishimatsu <yishimat@redhat.com>
+Message-ID: <5594C766.5010801@redhat.com>
+Date: Thu, 2 Jul 2015 01:08:54 -0400
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101
+ Thunderbird/38.0.1
+MIME-Version: 1.0
+In-Reply-To: <5594C62C.3030407@redhat.com>
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27
+Content-Length: 5064
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1182379
+
+The patch is back ported directory from the following upstream commit:
+
+commit 28e367cb78258e5d8d89edc5435804495661d1a3
+Author: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+Date:   Fri Nov 7 09:43:26 2014 +0900
+
+    [PATCH v5 3/5] Add module of generating table.
+
+    Set block size and generate basic information of block table.
+
+    Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
+    Signed-off-by: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+
+Resolves: rhbz#1182379
+Signed-off-by: Yasuaki Ishimatsu <yishimat@redhat.com>
+
+---
+ makedumpfile-1.5.7/makedumpfile.c |  109 ++++++++++++++++++++++++++++++++++++-
+ makedumpfile-1.5.7/makedumpfile.h |    4 ++
+ 2 files changed, 112 insertions(+), 1 deletions(-)
+
+diff --git a/makedumpfile-1.5.7/makedumpfile.c b/makedumpfile-1.5.7/makedumpfile.c
+index 4d2f077..5ffe8e1 100644
+--- a/makedumpfile-1.5.7/makedumpfile.c
++++ b/makedumpfile-1.5.7/makedumpfile.c
+@@ -5208,7 +5208,14 @@ create_dump_bitmap(void)
+ 	if (info->flag_cyclic) {
+ 		if (!prepare_bitmap2_buffer_cyclic())
+ 			goto out;
+-		info->num_dumpable = get_num_dumpable_cyclic();
++		if (info->flag_split) {
++			if (!prepare_splitblock_table())
++				goto out;
++
++			info->num_dumpable = get_num_dumpable_cyclic_withsplit();
++		} else {
++			info->num_dumpable = get_num_dumpable_cyclic();
++		}
+
+ 		if (!info->flag_elf_dumpfile)
+ 			free_bitmap2_buffer_cyclic();
+@@ -5745,6 +5752,61 @@ read_from_splitblock_table(char *entry)
+ 	return value;
+ }
+
++/*
++ * The splitblock size is specified as Kbyte with --splitblock-size <size> option.
++ * If not specified, set default value.
++ */
++int
++check_splitblock_size(void)
++{
++	if (info->splitblock_size) {
++		info->splitblock_size <<= 10;
++		if (info->splitblock_size == 0) {
++			ERRMSG("The splitblock size could not be 0. %s.\n",
++				strerror(errno));
++			return FALSE;
++		}
++		if (info->splitblock_size % info->page_size != 0) {
++			ERRMSG("The splitblock size must be align to page_size. %s.\n",
++				strerror(errno));
++			return FALSE;
++		}
++	} else {
++		info->splitblock_size = DEFAULT_SPLITBLOCK_SIZE;
++	}
++
++	return TRUE;
++}
++
++int
++prepare_splitblock_table(void)
++{
++	size_t table_size;
++
++	if (!check_splitblock_size())
++		return FALSE;
++
++	if ((splitblock = calloc(1, sizeof(struct SplitBlock))) == NULL) {
++		ERRMSG("Can't allocate memory for the splitblock. %s.\n",
++			strerror(errno));
++		return FALSE;
++	}
++
++	splitblock->page_per_splitblock = info->splitblock_size / info->page_size;
++	splitblock->num = divideup(info->max_mapnr, splitblock->page_per_splitblock);
++	splitblock->entry_size = calculate_entry_size();
++	table_size = splitblock->entry_size * splitblock->num;
++
++	splitblock->table = (char *)calloc(sizeof(char), table_size);
++	if (!splitblock->table) {
++		ERRMSG("Can't allocate memory for the splitblock_table. %s.\n",
++			 strerror(errno));
++		return FALSE;
++	}
++
++	return TRUE;
++}
++
+ mdf_pfn_t
+ get_num_dumpable(void)
+ {
+@@ -5760,6 +5822,45 @@ get_num_dumpable(void)
+ 	return num_dumpable;
+ }
+
++/*
++ * generate splitblock_table
++ * modified from function get_num_dumpable_cyclic
++ */
++mdf_pfn_t
++get_num_dumpable_cyclic_withsplit(void)
++{
++	mdf_pfn_t pfn, num_dumpable = 0;
++	mdf_pfn_t dumpable_pfn_num = 0, pfn_num = 0;
++	struct cycle cycle = {0};
++	int pos = 0;
++
++	pfn_memhole = info->max_mapnr;
++
++	for_each_cycle(0, info->max_mapnr, &cycle) {
++		if (!exclude_unnecessary_pages_cyclic(&cycle))
++			return FALSE;
++
++		if (info->flag_mem_usage)
++			exclude_zero_pages_cyclic(&cycle);
++
++		for (pfn = cycle.start_pfn; pfn < cycle.end_pfn; pfn++) {
++			if (is_dumpable_cyclic(info->partial_bitmap2, pfn, &cycle)) {
++				num_dumpable++;
++				dumpable_pfn_num++;
++			}
++			if (++pfn_num >= splitblock->page_per_splitblock) {
++				write_into_splitblock_table(splitblock->table + pos,
++							    dumpable_pfn_num);
++				pos += splitblock->entry_size;
++				pfn_num = 0;
++				dumpable_pfn_num = 0;
++			}
++		}
++	}
++
++	return num_dumpable;
++}
++
+ mdf_pfn_t
+ get_num_dumpable_cyclic(void)
+ {
+@@ -9717,6 +9818,12 @@ out:
+ 		if (info->page_buf != NULL)
+ 			free(info->page_buf);
+ 		free(info);
++
++		if (splitblock) {
++			if (splitblock->table)
++				free(splitblock->table);
++			free(splitblock);
++		}
+ 	}
+ 	free_elf_info();
+
+diff --git a/makedumpfile-1.5.7/makedumpfile.h b/makedumpfile-1.5.7/makedumpfile.h
+index a263631..f9d9332 100644
+--- a/makedumpfile-1.5.7/makedumpfile.h
++++ b/makedumpfile-1.5.7/makedumpfile.h
+@@ -1178,6 +1178,8 @@ extern struct DumpInfo		*info;
+ /*
+  * for cyclic_splitting mode,Manage memory by splitblock
+  */
++#define DEFAULT_SPLITBLOCK_SIZE (1LL << 30)
++
+ struct SplitBlock {
+ 	char *table;
+ 	long long num;
+@@ -1888,9 +1890,11 @@ struct elf_prstatus {
+  * Function Prototype.
+  */
+ mdf_pfn_t get_num_dumpable_cyclic(void);
++mdf_pfn_t get_num_dumpable_cyclic_withsplit(void);
+ int get_loads_dumpfile_cyclic(void);
+ int initial_xen(void);
+ unsigned long long get_free_memory_size(void);
+ int calculate_cyclic_buffer_size(void);
++int prepare_splitblock_table(void);
+
+ #endif /* MAKEDUMPFILE_H */
+-- 
+1.7.1
+
diff --git a/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-support-for-splitblock-size.patch b/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-support-for-splitblock-size.patch
new file mode 100644
index 0000000..31df8b8
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-support-for-splitblock-size.patch
@@ -0,0 +1,128 @@
+Return-Path: yishimat@redhat.com
+Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO
+ zmta01.collab.prod.int.phx2.redhat.com) (10.5.81.8) by
+ zmail24.collab.prod.int.phx2.redhat.com with LMTP; Thu, 2 Jul 2015 01:10:45
+ -0400 (EDT)
+Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26])
+	by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 5C0B61835A9;
+	Thu,  2 Jul 2015 01:10:45 -0400 (EDT)
+Received: from [10.3.112.13] ([10.3.112.13])
+	by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t625AhFu027595;
+	Thu, 2 Jul 2015 01:10:43 -0400
+Subject: [RHEL7.2 PATCH resend v3 5/5] Add support for --splitblock-size.
+To: kexec-kdump-list@redhat.com
+References: <55929D94.4020500@redhat.com> <5594C62C.3030407@redhat.com>
+Cc: Minfei Huang <mhuang@redhat.com>, bhe@redhat.com, yishimat@redhat.com
+From: Yasuaki Ishimatsu <yishimat@redhat.com>
+Message-ID: <5594C7D2.8030300@redhat.com>
+Date: Thu, 2 Jul 2015 01:10:42 -0400
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101
+ Thunderbird/38.0.1
+MIME-Version: 1.0
+In-Reply-To: <5594C62C.3030407@redhat.com>
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26
+Content-Length: 4028
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1182379
+
+The patch is back ported directory from the following upstream commit:
+
+commit 33521799757a52f0e97cbfb7c6a5e24de3b8cb50
+Author: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+Date:   Fri Nov 7 09:45:04 2014 +0900
+
+    [PATCH v5 5/5] Add support for --splitblock-size.
+
+    Use --splitblock-size to specify splitblock size (KB)
+    When --split is specified in cyclic mode,splitblock table will be
+    generated in create_dump_bitmap().
+
+    Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
+    Signed-off-by: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+
+Resolves: rhbz#1182379
+Signed-off-by: Yasuaki Ishimatsu <yishimat@redhat.com>
+
+---
+ makedumpfile-1.5.7/makedumpfile.8 |   10 ++++++++++
+ makedumpfile-1.5.7/makedumpfile.c |    4 ++++
+ makedumpfile-1.5.7/makedumpfile.h |    1 +
+ makedumpfile-1.5.7/print_info.c   |    5 +++++
+ 4 files changed, 20 insertions(+), 0 deletions(-)
+
+diff --git a/makedumpfile-1.5.7/makedumpfile.8 b/makedumpfile-1.5.7/makedumpfile.8
+index 9cb12c0..5e121fd 100644
+--- a/makedumpfile-1.5.7/makedumpfile.8
++++ b/makedumpfile-1.5.7/makedumpfile.8
+@@ -386,6 +386,16 @@ size, so ordinary users don't need to specify this option.
+ # makedumpfile \-\-cyclic\-buffer 1024 \-d 31 \-x vmlinux /proc/vmcore dumpfile
+
+ .TP
++\fB\-\-splitblock\-size\fR \fIsplitblock_size\fR
++Specify the splitblock size in kilo bytes for analysis in the cyclic mode with --split.
++If --splitblock N is specified, difference of each splitted dumpfile size is at most N
++kilo bytes.
++.br
++.B Example:
++.br
++# makedumpfile \-\-splitblock\-size 1024 \-d 31 \-x vmlinux \-\-split /proc/vmcore dumpfile1 dumpfile2
++
++.TP
+ \fB\-\-non\-cyclic\fR
+ Running in the non-cyclic mode, this mode uses the old filtering logic same as v1.4.4 or before.
+ If you feel the cyclic mode is too slow, please try this mode.
+diff --git a/makedumpfile-1.5.7/makedumpfile.c b/makedumpfile-1.5.7/makedumpfile.c
+index c4309af..f3e76c9 100644
+--- a/makedumpfile-1.5.7/makedumpfile.c
++++ b/makedumpfile-1.5.7/makedumpfile.c
+@@ -9570,6 +9570,7 @@ static struct option longopts[] = {
+ 	{"eppic", required_argument, NULL, OPT_EPPIC},
+ 	{"non-mmap", no_argument, NULL, OPT_NON_MMAP},
+ 	{"mem-usage", no_argument, NULL, OPT_MEM_USAGE},
++	{"splitblock-size", required_argument, NULL, OPT_SPLITBLOCK_SIZE},
+ 	{0, 0, 0, 0}
+ };
+
+@@ -9710,6 +9711,9 @@ main(int argc, char *argv[])
+ 		case OPT_CYCLIC_BUFFER:
+ 			info->bufsize_cyclic = atoi(optarg);
+ 			break;
++		case OPT_SPLITBLOCK_SIZE:
++			info->splitblock_size = atoi(optarg);
++			break;
+ 		case '?':
+ 			MSG("Commandline parameter is invalid.\n");
+ 			MSG("Try `makedumpfile --help' for more information.\n");
+diff --git a/makedumpfile-1.5.7/makedumpfile.h b/makedumpfile-1.5.7/makedumpfile.h
+index f9d9332..0cb54a3 100644
+--- a/makedumpfile-1.5.7/makedumpfile.h
++++ b/makedumpfile-1.5.7/makedumpfile.h
+@@ -1885,6 +1885,7 @@ struct elf_prstatus {
+ #define OPT_EPPIC               OPT_START+12
+ #define OPT_NON_MMAP            OPT_START+13
+ #define OPT_MEM_USAGE            OPT_START+14
++#define OPT_SPLITBLOCK_SIZE	OPT_START+15
+
+ /*
+  * Function Prototype.
+diff --git a/makedumpfile-1.5.7/print_info.c b/makedumpfile-1.5.7/print_info.c
+index f6342d3..efdf578 100644
+--- a/makedumpfile-1.5.7/print_info.c
++++ b/makedumpfile-1.5.7/print_info.c
+@@ -203,6 +203,11 @@ print_usage(void)
+ 	MSG("      By default, BUFFER_SIZE will be calculated automatically depending on\n");
+ 	MSG("      system memory size, so ordinary users don't need to specify this option.\n");
+ 	MSG("\n");
++	MSG("  [--splitblock-size SPLITBLOCK_SIZE]:\n");
++	MSG("      Specify the splitblock size in kilo bytes for analysis in the cyclic mode\n");
++	MSG("      with --split. If --splitblock N is specified, difference of each splitted\n");
++	MSG("      dumpfile size is at most N kilo bytes.\n");
++	MSG("\n");
+ 	MSG("  [--non-cyclic]:\n");
+ 	MSG("      Running in the non-cyclic mode, this mode uses the old filtering logic\n");
+ 	MSG("      same as v1.4.4 or before.\n");
+-- 
+1.7.1
+
diff --git a/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-support-for-splitblock.patch b/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-support-for-splitblock.patch
new file mode 100644
index 0000000..12e0514
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-support-for-splitblock.patch
@@ -0,0 +1,146 @@
+Return-Path: yishimat@redhat.com
+Received: from zmta05.collab.prod.int.phx2.redhat.com (LHLO
+ zmta05.collab.prod.int.phx2.redhat.com) (10.5.81.12) by
+ zmail24.collab.prod.int.phx2.redhat.com with LMTP; Thu, 2 Jul 2015 01:06:36
+ -0400 (EDT)
+Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26])
+	by zmta05.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9A5FA17C114;
+	Thu,  2 Jul 2015 01:06:36 -0400 (EDT)
+Received: from [10.3.112.13] ([10.3.112.13])
+	by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t6256Wbm025889;
+	Thu, 2 Jul 2015 01:06:33 -0400
+Subject: [RHEL7.2 PATCH resend v3 1/5] Add support for splitblock.
+To: kexec-kdump-list@redhat.com
+References: <55929D94.4020500@redhat.com> <5594C62C.3030407@redhat.com>
+Cc: Minfei Huang <mhuang@redhat.com>, bhe@redhat.com, yishimat@redhat.com
+From: Yasuaki Ishimatsu <yishimat@redhat.com>
+Message-ID: <5594C6D8.5060601@redhat.com>
+Date: Thu, 2 Jul 2015 01:06:32 -0400
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101
+ Thunderbird/38.0.1
+MIME-Version: 1.0
+In-Reply-To: <5594C62C.3030407@redhat.com>
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26
+Content-Length: 3498
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1182379
+
+The patch is back ported directory from the following upstream commit:
+
+commit c7825d45999daf09bd89a08d08219261023dcf11
+Author: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+Date:   Fri Nov 7 09:42:18 2014 +0900
+
+    [PATCH v5 1/5] Add support for splitblock.
+
+    When --split option is specified, fair I/O workloads shoud be assigned
+    for each process. So the start and end pfn of each dumpfile should be
+    calculated with excluding unnecessary pages. However, it costs a lot of
+    time to execute excluding for the whole memory. That is why struct
+    SplitBlock exists. Struct SplitBlock is designed to manage memory, main
+    for recording the number of dumpable pages. We can use the number of
+    dumpable pages to calculate start and end pfn instead of execute exclud
+    for the whole memory.
+
+    The char array *table in struct SplitBlock is used to record the number
+    dumpable pages.
+    The table entry size is calculated as
+                            divideup(log2(splitblock_size / page_size), 8)
+    The table entry size is calculated, so that the
+    space table taken will be small enough. And the code will also have a
+    good performence when the number of pages in one splitblock is big enou
+
+    Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
+    Signed-off-by: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+
+Resolves: rhbz#1182379
+Signed-off-by: Yasuaki Ishimatsu <yishimat@redhat.com>
+
+---
+ makedumpfile-1.5.7/makedumpfile.c |   31 +++++++++++++++++++++++++++++++
+ makedumpfile-1.5.7/makedumpfile.h |   14 ++++++++++++++
+ 2 files changed, 45 insertions(+), 0 deletions(-)
+
+diff --git a/makedumpfile-1.5.7/makedumpfile.c b/makedumpfile-1.5.7/makedumpfile.c
+index b4d43d8..a4c3eee 100644
+--- a/makedumpfile-1.5.7/makedumpfile.c
++++ b/makedumpfile-1.5.7/makedumpfile.c
+@@ -34,6 +34,7 @@ struct srcfile_table	srcfile_table;
+
+ struct vm_table		vt = { 0 };
+ struct DumpInfo		*info = NULL;
++struct SplitBlock		*splitblock = NULL;
+
+ char filename_stdout[] = FILENAME_STDOUT;
+
+@@ -5685,6 +5686,36 @@ out:
+ 	return ret;
+ }
+
++/*
++ * cyclic_split mode:
++ *	manage memory by splitblocks,
++ *	divide memory into splitblocks
++ *	use splitblock_table to record numbers of dumpable pages in each
++ *	splitblock
++ */
++
++/*
++ * calculate entry size based on the amount of pages in one splitblock
++ */
++int
++calculate_entry_size(void)
++{
++	int entry_num = 1;
++	int count = 1;
++	int entry_size;
++
++	while (entry_num < splitblock->page_per_splitblock) {
++		entry_num = entry_num << 1;
++		count++;
++	}
++
++	entry_size = count / BITPERBYTE;
++	if (count % BITPERBYTE)
++		entry_size++;
++
++	return entry_size;
++}
++
+ mdf_pfn_t
+ get_num_dumpable(void)
+ {
+diff --git a/makedumpfile-1.5.7/makedumpfile.h b/makedumpfile-1.5.7/makedumpfile.h
+index 96830b0..a263631 100644
+--- a/makedumpfile-1.5.7/makedumpfile.h
++++ b/makedumpfile-1.5.7/makedumpfile.h
+@@ -1168,10 +1168,24 @@ struct DumpInfo {
+ 	 */
+ 	int (*page_is_buddy)(unsigned long flags, unsigned int _mapcount,
+ 			     unsigned long private, unsigned int _count);
++	/*
++	 * for cyclic_splitting mode, setup splitblock_size
++	 */
++	long long splitblock_size;
+ };
+ extern struct DumpInfo		*info;
+
+ /*
++ * for cyclic_splitting mode,Manage memory by splitblock
++ */
++struct SplitBlock {
++	char *table;
++	long long num;
++	long long page_per_splitblock;
++	int entry_size;                 /* counted by byte */
++};
++
++/*
+  * kernel VM-related data
+  */
+ struct vm_table {
+-- 
+1.7.1
+
diff --git a/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-tools-for-reading-and-writing-from-.patch b/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-tools-for-reading-and-writing-from-.patch
new file mode 100644
index 0000000..cd5a144
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-makedumpfile-Add-tools-for-reading-and-writing-from-.patch
@@ -0,0 +1,94 @@
+Return-Path: yishimat@redhat.com
+Received: from zmta05.collab.prod.int.phx2.redhat.com (LHLO
+ zmta05.collab.prod.int.phx2.redhat.com) (10.5.81.12) by
+ zmail24.collab.prod.int.phx2.redhat.com with LMTP; Thu, 2 Jul 2015 01:08:13
+ -0400 (EDT)
+Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24])
+	by zmta05.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 7D03B17C114;
+	Thu,  2 Jul 2015 01:08:13 -0400 (EDT)
+Received: from [10.3.112.13] ([10.3.112.13])
+	by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t6258AD6015893;
+	Thu, 2 Jul 2015 01:08:11 -0400
+Subject: [RHEL7.2 PATCH resend v3 2/5] Add tools for reading and writing from
+ splitblock table.
+To: kexec-kdump-list@redhat.com
+References: <55929D94.4020500@redhat.com> <5594C62C.3030407@redhat.com>
+Cc: Minfei Huang <mhuang@redhat.com>, bhe@redhat.com, yishimat@redhat.com
+From: Yasuaki Ishimatsu <yishimat@redhat.com>
+Message-ID: <5594C73A.6080509@redhat.com>
+Date: Thu, 2 Jul 2015 01:08:10 -0400
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101
+ Thunderbird/38.0.1
+MIME-Version: 1.0
+In-Reply-To: <5594C62C.3030407@redhat.com>
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24
+Content-Length: 1602
+
+Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1182379
+
+The patch is back ported directory from the following upstream commit:
+
+commit 11dcbfe2ebd1dec37c3a00dc8ee522504c7ed35c
+Author: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+Date:   Fri Nov 7 09:42:25 2014 +0900
+
+    [PATCH v5 2/5] Add tools for reading and writing from splitblock table.
+
+    gdded in this patch, is used for writing and reading value
+    from the char array in struct SplitBlock.
+
+    Signed-off-by: Qiao Nuohan <qiaonuohan@cn.fujitsu.com>
+    Signed-off-by: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+
+Resolves: rhbz#1182379
+Signed-off-by: Yasuaki Ishimatsu <yishimat@redhat.com>
+
+---
+ makedumpfile-1.5.7/makedumpfile.c |   29 +++++++++++++++++++++++++++++
+ 1 files changed, 29 insertions(+), 0 deletions(-)
+
+diff --git a/makedumpfile-1.5.7/makedumpfile.c b/makedumpfile-1.5.7/makedumpfile.c
+index a4c3eee..4d2f077 100644
+--- a/makedumpfile-1.5.7/makedumpfile.c
++++ b/makedumpfile-1.5.7/makedumpfile.c
+@@ -5716,6 +5716,35 @@ calculate_entry_size(void)
+ 	return entry_size;
+ }
+
++void
++write_into_splitblock_table(char *entry,
++				unsigned long long value)
++{
++	char temp;
++	int i = 0;
++
++	while (i++ < splitblock->entry_size) {
++		temp = value & 0xff;
++		value = value >> BITPERBYTE;
++		*entry = temp;
++		entry++;
++	}
++}
++
++unsigned long long
++read_from_splitblock_table(char *entry)
++{
++	unsigned long long value = 0;
++	int i;
++
++	for (i = splitblock->entry_size; i > 0; i--) {
++		value = value << BITPERBYTE;
++		value += *(entry + i - 1) & 0xff;
++	}
++
++	return value;
++}
++
+ mdf_pfn_t
+ get_num_dumpable(void)
+ {
+-- 
+1.7.1
+
diff --git a/SOURCES/kexec-tools-2.0.8-makedumpfile-Fix-reassemble_kdump_header.patch b/SOURCES/kexec-tools-2.0.8-makedumpfile-Fix-reassemble_kdump_header.patch
new file mode 100644
index 0000000..39c5c48
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-makedumpfile-Fix-reassemble_kdump_header.patch
@@ -0,0 +1,73 @@
+Return-Path: yishimat@redhat.com
+Received: from zmta02.collab.prod.int.phx2.redhat.com (LHLO
+ zmta02.collab.prod.int.phx2.redhat.com) (10.5.81.9) by
+ zmail24.collab.prod.int.phx2.redhat.com with LMTP; Thu, 2 Jul 2015 01:16:42
+ -0400 (EDT)
+Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27])
+	by zmta02.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 9997C122359;
+	Thu,  2 Jul 2015 01:16:42 -0400 (EDT)
+Received: from [10.3.112.13] ([10.3.112.13])
+	by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t625Geo3028836;
+	Thu, 2 Jul 2015 01:16:41 -0400
+Subject: [RHEL7.2 PATCH resend v3 4/4] Fix reassemble_kdump_header().
+To: kexec-kdump-list@redhat.com
+References: <55929BD5.7050709@redhat.com> <5594C856.6050503@redhat.com>
+Cc: Minfei Huang <mhuang@redhat.com>, bhe@redhat.com, yishimat@redhat.com
+From: Yasuaki Ishimatsu <yishimat@redhat.com>
+Message-ID: <5594C937.2060303@redhat.com>
+Date: Thu, 2 Jul 2015 01:16:39 -0400
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101
+ Thunderbird/38.0.1
+MIME-Version: 1.0
+In-Reply-To: <5594C856.6050503@redhat.com>
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27
+Content-Length: 1349
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1182377
+
+The patch is back ported directory from the following upstream commit:
+
+commit 45a1885e747c3833d5df770d0f2c5571a838f55a
+Author: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+Date:   Mon Oct 20 13:40:10 2014 +0900
+
+    [PATCH v4 4/4] Fix reassemble_kdump_header().
+
+    Fix it to take over incomplete flags of all dump file.
+
+    Singed-of-by: Zhou Wenjian <zhouwj-fnst@cn.fujitsu.com>
+
+Resolves: rhbz#1182377
+Signed-off-by: Yasuaki Ishimatsu <yishimat@redhat.com>
+Acked-by: Minfei Huang <mhuang@redhat.com>
+
+---
+ makedumpfile-1.5.7/makedumpfile.c |   10 ++++++++--
+ 1 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/makedumpfile-1.5.7/makedumpfile.c b/makedumpfile-1.5.7/makedumpfile.c
+index 4dba83e..f072069 100644
+--- a/makedumpfile-1.5.7/makedumpfile.c
++++ b/makedumpfile-1.5.7/makedumpfile.c
+@@ -8695,8 +8695,14 @@ reassemble_kdump_header(void)
+ 	/*
+ 	 * Write common header.
+ 	 */
+-	if (!read_disk_dump_header(&dh, SPLITTING_DUMPFILE(0)))
+-		return FALSE;
++	int i;
++	for ( i = 0; i < info->num_dumpfile; i++){
++		if (!read_disk_dump_header(&dh, SPLITTING_DUMPFILE(i)))
++			return FALSE;
++		int status = dh.status & DUMP_DH_COMPRESSED_INCOMPLETE;
++		if (status)
++			break;
++	}
+
+ 	if (lseek(info->fd_dumpfile, 0x0, SEEK_SET) < 0) {
+ 		ERRMSG("Can't seek a file(%s). %s\n",
+-- 
+1.7.1
+
diff --git a/SOURCES/kexec-tools-2.0.8-makedumpfile-Implementation-of-dealing-with-kdump-co.patch b/SOURCES/kexec-tools-2.0.8-makedumpfile-Implementation-of-dealing-with-kdump-co.patch
new file mode 100644
index 0000000..2d56069
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-makedumpfile-Implementation-of-dealing-with-kdump-co.patch
@@ -0,0 +1,184 @@
+Return-Path: yishimat@redhat.com
+Received: from zmta01.collab.prod.int.phx2.redhat.com (LHLO
+ zmta01.collab.prod.int.phx2.redhat.com) (10.5.81.8) by
+ zmail24.collab.prod.int.phx2.redhat.com with LMTP; Thu, 2 Jul 2015 01:15:32
+ -0400 (EDT)
+Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26])
+	by zmta01.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id C144F1835B7;
+	Thu,  2 Jul 2015 01:15:32 -0400 (EDT)
+Received: from [10.3.112.13] ([10.3.112.13])
+	by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t625FTop028995;
+	Thu, 2 Jul 2015 01:15:30 -0400
+Subject: [RHEL7.2 PATCH resend v3 3/4] Implementation of dealing with
+ kdump-compressed dumpfile with ENOSPC error.
+To: kexec-kdump-list@redhat.com
+References: <55929BD5.7050709@redhat.com> <5594C856.6050503@redhat.com>
+Cc: Minfei Huang <mhuang@redhat.com>, bhe@redhat.com, yishimat@redhat.com
+From: Yasuaki Ishimatsu <yishimat@redhat.com>
+Message-ID: <5594C8F1.3070006@redhat.com>
+Date: Thu, 2 Jul 2015 01:15:29 -0400
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101
+ Thunderbird/38.0.1
+MIME-Version: 1.0
+In-Reply-To: <5594C856.6050503@redhat.com>
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26
+Content-Length: 4314
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1182377
+
+The patch is back ported directory from the following upstream commit:
+
+commit 76025d3ca228affdd124b874b06d7a69573391e9
+Author: Wang Xiao <wangx.fnst@cn.fujitsu.com>
+Date:   Mon Oct 20 13:39:16 2014 +0900
+
+    [PATCH v4 3/4] Implementation of dealing with kdump-compressed dumpfile with ENOSPC error.
+
+    kdump-compressed:
+    Dump the bitmap before any page header and page data. This format use
+    "status" of "disk_dump_header" to indicate that it has been modified.
+
+    Signed-of-by: Wang Xiao <wangx.fnst@cn.fujitsu.com>
+
+Resolves: rhbz#1182377
+Signed-off-by: Yasuaki Ishimatsu <yishimat@redhat.com>
+Acked-by: Minfei Huang <mhuang@redhat.com
+
+---
+ makedumpfile-1.5.7/diskdump_mod.h |    2 +
+ makedumpfile-1.5.7/makedumpfile.c |   80 ++++++++++++++++++++++++++++++++++--
+ 2 files changed, 77 insertions(+), 5 deletions(-)
+
+diff --git a/makedumpfile-1.5.7/diskdump_mod.h b/makedumpfile-1.5.7/diskdump_mod.h
+index dd24eb2..275ed83 100644
+--- a/makedumpfile-1.5.7/diskdump_mod.h
++++ b/makedumpfile-1.5.7/diskdump_mod.h
+@@ -95,6 +95,8 @@ struct kdump_sub_header {
+ #define DUMP_DH_COMPRESSED_LZO	0x2	/* paged is compressed with lzo */
+ #define DUMP_DH_COMPRESSED_SNAPPY	0x4
+ 					/* paged is compressed with snappy */
++#define DUMP_DH_COMPRESSED_INCOMPLETE	0x8
++					/* indicate an incomplete dumpfile */
+
+ /* descriptor of each page for vmcore */
+ typedef struct page_desc {
+diff --git a/makedumpfile-1.5.7/makedumpfile.c b/makedumpfile-1.5.7/makedumpfile.c
+index 141d290..4dba83e 100644
+--- a/makedumpfile-1.5.7/makedumpfile.c
++++ b/makedumpfile-1.5.7/makedumpfile.c
+@@ -3847,10 +3847,80 @@ out_close_file:
+ }
+
+ int
++check_and_modify_kdump_headers(char *filename) {
++	int fd, ret = FALSE;
++	struct disk_dump_header dh;
++
++	if (!read_disk_dump_header(&dh, filename))
++		return FALSE;
++
++	if ((fd = open(filename, O_RDWR)) < 0) {
++		ERRMSG("Can't open the dump file(%s). %s\n",
++		       filename, strerror(errno));
++		return FALSE;
++	}
++
++	/*
++	 * Set the incomplete flag to the status of disk_dump_header.
++	 */
++	dh.status |= DUMP_DH_COMPRESSED_INCOMPLETE;
++
++	/*
++	 * It's safe to overwrite the disk_dump_header.
++	 */
++	if (!write_buffer(fd, 0, &dh, sizeof(struct disk_dump_header), filename))
++		goto out_close_file;
++
++	ret = TRUE;
++out_close_file:
++	if (close(fd) < 0) {
++		ERRMSG("Can't close the dump file(%s). %s\n",
++		       filename, strerror(errno));
++	}
++
++	return ret;
++}
++
++int
++check_and_modify_multiple_kdump_headers() {
++	int i, status, ret = TRUE;
++	pid_t pid;
++	pid_t array_pid[info->num_dumpfile];
++
++	for (i = 0; i < info->num_dumpfile; i++) {
++		if ((pid = fork()) < 0) {
++			return FALSE;
++
++		} else if (pid == 0) { /* Child */
++			if (!check_and_modify_kdump_headers(SPLITTING_DUMPFILE(i)))
++				exit(1);
++			exit(0);
++		}
++		array_pid[i] = pid;
++	}
++
++	for (i = 0; i < info->num_dumpfile; i++) {
++		waitpid(array_pid[i], &status, WUNTRACED);
++		if (!WIFEXITED(status) || WEXITSTATUS(status) == 1) {
++			ERRMSG("Check and modify the incomplete dumpfile(%s) failed.\n",
++			       SPLITTING_DUMPFILE(i));
++			ret = FALSE;
++		}
++	}
++
++	return ret;
++}
++
++int
+ check_and_modify_headers()
+ {
+ 	if (info->flag_elf_dumpfile)
+ 		return check_and_modify_elf_headers(info->name_dumpfile);
++	else
++		if(info->flag_split)
++			return check_and_modify_multiple_kdump_headers();
++		else
++			return check_and_modify_kdump_headers(info->name_dumpfile);
+ 	return FALSE;
+ }
+
+@@ -7123,11 +7193,11 @@ write_kdump_pages_and_bitmap_cyclic(struct cache_data *cd_header, struct cache_d
+ 		if (!exclude_unnecessary_pages_cyclic(&cycle))
+ 			return FALSE;
+
+-		if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero,
+-					&offset_data, &cycle))
++		if (!write_kdump_bitmap2_cyclic(&cycle))
+ 			return FALSE;
+
+-		if (!write_kdump_bitmap2_cyclic(&cycle))
++		if (!write_kdump_pages_cyclic(cd_header, cd_page, &pd_zero,
++					&offset_data, &cycle))
+ 			return FALSE;
+ 	}
+
+@@ -8127,12 +8197,12 @@ writeout_dumpfile(void)
+ 	} else {
+ 		if (!write_kdump_header())
+ 			goto out;
++		if (!write_kdump_bitmap())
++			goto out;
+ 		if (!write_kdump_pages(&cd_header, &cd_page))
+ 			goto out;
+ 		if (!write_kdump_eraseinfo(&cd_page))
+ 			goto out;
+-		if (!write_kdump_bitmap())
+-			goto out;
+ 	}
+ 	if (info->flag_flatten) {
+ 		if (!write_end_flat_header())
+-- 
+1.7.1
+
diff --git a/SOURCES/kexec-tools-2.0.8-makedumpfile-Make-get_elf64_phdr-get_elf32_phdr-publ.patch b/SOURCES/kexec-tools-2.0.8-makedumpfile-Make-get_elf64_phdr-get_elf32_phdr-publ.patch
new file mode 100644
index 0000000..5599dbc
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-makedumpfile-Make-get_elf64_phdr-get_elf32_phdr-publ.patch
@@ -0,0 +1,160 @@
+Return-Path: yishimat@redhat.com
+Received: from zmta04.collab.prod.int.phx2.redhat.com (LHLO
+ zmta04.collab.prod.int.phx2.redhat.com) (10.5.81.11) by
+ zmail24.collab.prod.int.phx2.redhat.com with LMTP; Thu, 2 Jul 2015 01:14:06
+ -0400 (EDT)
+Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23])
+	by zmta04.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 08529DA114;
+	Thu,  2 Jul 2015 01:14:06 -0400 (EDT)
+Received: from [10.3.112.13] ([10.3.112.13])
+	by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t625E1nH006506;
+	Thu, 2 Jul 2015 01:14:03 -0400
+Subject: [RHEL7.2 PATCH resend v3 1/4] Make get_elf64_phdr()/get_elf32_phdr()
+ public.
+To: kexec-kdump-list@redhat.com
+References: <55929BD5.7050709@redhat.com> <5594C856.6050503@redhat.com>
+Cc: Minfei Huang <mhuang@redhat.com>, bhe@redhat.com, yishimat@redhat.com
+From: Yasuaki Ishimatsu <yishimat@redhat.com>
+Message-ID: <5594C899.1070106@redhat.com>
+Date: Thu, 2 Jul 2015 01:14:01 -0400
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101
+ Thunderbird/38.0.1
+MIME-Version: 1.0
+In-Reply-To: <5594C856.6050503@redhat.com>
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23
+Content-Length: 3805
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1182377
+
+The patch is back ported directory from the following upstream commit:
+
+commit 3182be907d27584cd04dfb03d0ec5bf7134da87f
+Author: Wang Xiao <wangx.fnst@cn.fujitsu.com>
+Date:   Mon Oct 20 13:38:45 2014 +0900
+
+    [PATCH v4 1/4] Make get_elf64_phdr()/get_elf32_phdr() public.
+
+    Move the following two functions from internal function to external
+    function.
+
+    get_elf64_phdr(int fd, char *filename, int index, Elf64_Phdr *phdr)
+    get_elf32_phdr(int fd, char *filename, int index, Elf32_Phdr *phdr)
+
+    Signed-of-by: Wang Xiao <wangx.fnst@cn.fujitsu.com>
+
+Resolves: rhbz#1182377
+Signed-off-by: Yasuaki Ishimatsu <yishimat@redhat.com>
+Acked-by: Minfei Huang <mhuang@redhat.com>
+
+---
+ makedumpfile-1.5.7/elf_info.c |   71 ++++++++++++++++++++---------------------
+ makedumpfile-1.5.7/elf_info.h |    2 +
+ 2 files changed, 37 insertions(+), 36 deletions(-)
+
+diff --git a/makedumpfile-1.5.7/elf_info.c b/makedumpfile-1.5.7/elf_info.c
+index 5be1990..24936d4 100644
+--- a/makedumpfile-1.5.7/elf_info.c
++++ b/makedumpfile-1.5.7/elf_info.c
+@@ -95,42 +95,6 @@ static unsigned long		size_xen_crash_info;
+  * Internal functions.
+  */
+ static int
+-get_elf64_phdr(int fd, char *filename, int index, Elf64_Phdr *phdr)
+-{
+-	off_t offset;
+-
+-	offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * index;
+-
+-	if (lseek(fd, offset, SEEK_SET) < 0) {
+-		ERRMSG("Can't seek %s. %s\n", filename, strerror(errno));
+-		return FALSE;
+-	}
+-	if (read(fd, phdr, sizeof(Elf64_Phdr)) != sizeof(Elf64_Phdr)) {
+-		ERRMSG("Can't read %s. %s\n", filename, strerror(errno));
+-		return FALSE;
+-	}
+-	return TRUE;
+-}
+-
+-static int
+-get_elf32_phdr(int fd, char *filename, int index, Elf32_Phdr *phdr)
+-{
+-	off_t offset;
+-
+-	offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * index;
+-
+-	if (lseek(fd, offset, SEEK_SET) < 0) {
+-		ERRMSG("Can't seek %s. %s\n", filename, strerror(errno));
+-		return FALSE;
+-	}
+-	if (read(fd, phdr, sizeof(Elf32_Phdr)) != sizeof(Elf32_Phdr)) {
+-		ERRMSG("Can't read %s. %s\n", filename, strerror(errno));
+-		return FALSE;
+-	}
+-	return TRUE;
+-}
+-
+-static int
+ check_elf_format(int fd, char *filename, int *phnum, unsigned int *num_load)
+ {
+ 	int i;
+@@ -446,6 +410,41 @@ int set_kcore_vmcoreinfo(uint64_t vmcoreinfo_addr, uint64_t vmcoreinfo_len)
+ /*
+  * External functions.
+  */
++int
++get_elf64_phdr(int fd, char *filename, int index, Elf64_Phdr *phdr)
++{
++	off_t offset;
++
++	offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * index;
++
++	if (lseek(fd, offset, SEEK_SET) < 0) {
++		ERRMSG("Can't seek %s. %s\n", filename, strerror(errno));
++		return FALSE;
++	}
++	if (read(fd, phdr, sizeof(Elf64_Phdr)) != sizeof(Elf64_Phdr)) {
++		ERRMSG("Can't read %s. %s\n", filename, strerror(errno));
++		return FALSE;
++	}
++	return TRUE;
++}
++
++int
++get_elf32_phdr(int fd, char *filename, int index, Elf32_Phdr *phdr)
++{
++	off_t offset;
++
++	offset = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * index;
++
++	if (lseek(fd, offset, SEEK_SET) < 0) {
++		ERRMSG("Can't seek %s. %s\n", filename, strerror(errno));
++		return FALSE;
++	}
++	if (read(fd, phdr, sizeof(Elf32_Phdr)) != sizeof(Elf32_Phdr)) {
++		ERRMSG("Can't read %s. %s\n", filename, strerror(errno));
++		return FALSE;
++	}
++	return TRUE;
++}
+
+ /*
+  * Convert Physical Address to File Offset.
+diff --git a/makedumpfile-1.5.7/elf_info.h b/makedumpfile-1.5.7/elf_info.h
+index cbabf8a..e712253 100644
+--- a/makedumpfile-1.5.7/elf_info.h
++++ b/makedumpfile-1.5.7/elf_info.h
+@@ -27,6 +27,8 @@
+
+ #define MAX_SIZE_NHDR	MAX(sizeof(Elf64_Nhdr), sizeof(Elf32_Nhdr))
+
++int get_elf64_phdr(int fd, char *filename, int index, Elf64_Phdr *phdr);
++int get_elf32_phdr(int fd, char *filename, int index, Elf32_Phdr *phdr);
+
+ off_t paddr_to_offset(unsigned long long paddr);
+ off_t paddr_to_offset2(unsigned long long paddr, off_t hint);
+-- 
+1.7.1
+
diff --git a/SOURCES/kexec-tools-2.0.8-makedumpfile-Make-the-incomplete-dumpfile-generated-.patch b/SOURCES/kexec-tools-2.0.8-makedumpfile-Make-the-incomplete-dumpfile-generated-.patch
new file mode 100644
index 0000000..e53fa33
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-makedumpfile-Make-the-incomplete-dumpfile-generated-.patch
@@ -0,0 +1,230 @@
+Return-Path: yishimat@redhat.com
+Received: from zmta03.collab.prod.int.phx2.redhat.com (LHLO
+ zmta03.collab.prod.int.phx2.redhat.com) (10.5.81.10) by
+ zmail24.collab.prod.int.phx2.redhat.com with LMTP; Thu, 2 Jul 2015 01:14:45
+ -0400 (EDT)
+Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23])
+	by zmta03.collab.prod.int.phx2.redhat.com (Postfix) with ESMTP id 4A6B242574;
+	Thu,  2 Jul 2015 01:14:45 -0400 (EDT)
+Received: from [10.3.112.13] ([10.3.112.13])
+	by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t625EgU7006706;
+	Thu, 2 Jul 2015 01:14:43 -0400
+Subject: [RHEL7.2 PATCH resend v3 2/4] Make the incomplete dumpfile generated
+ by ENOSPC error analyzable.
+To: kexec-kdump-list@redhat.com
+References: <55929BD5.7050709@redhat.com> <5594C856.6050503@redhat.com>
+Cc: Minfei Huang <mhuang@redhat.com>, bhe@redhat.com, yishimat@redhat.com
+From: Yasuaki Ishimatsu <yishimat@redhat.com>
+Message-ID: <5594C8C2.8080603@redhat.com>
+Date: Thu, 2 Jul 2015 01:14:42 -0400
+User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101
+ Thunderbird/38.0.1
+MIME-Version: 1.0
+In-Reply-To: <5594C856.6050503@redhat.com>
+Content-Type: text/plain; charset=utf-8
+Content-Transfer-Encoding: 7bit
+X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23
+Content-Length: 5485
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1182377
+
+The patch is back ported directory from the following upstream commit:
+
+commit e39216fce9f73759509ec158e39c289e6c211125
+Author: Wang Xiao <wangx.fnst@cn.fujitsu.com>
+Date:   Mon Oct 20 13:39:03 2014 +0900
+
+    [PATCH v4 2/4] Make the incomplete dumpfile generated by ENOSPC error analyzable.
+
+    Since the incomplete dumpfile generated by ENOSPC error can't be anylyzed
+    by crash utility, but sometimes this file may contain important information
+    and the panic problem won't be reproduced, then we came up with an idea to
+    modify the exist data of the incomplete dumpfile to make it analyzable by
+    crash utility. And each of those dumpfiles has a flag to indicate that it
+    has been modified. As there are two formats of these dumpfiles, different
+    methods and flags are needed to deal with each of them,
+
+    elf:
+    This format use the "e_flags" of "elf header" to indicate that it has been
+    modified.
+
+    The method of dealing with "kdump-compressed" format dumpfiles is
+    implemented
+    in the next patch.
+
+    Signed-of-by: Wang Xiao <wangx.fnst@cn.fujitsu.com>
+
+Resolves: rhbz#1182377
+Signed-off-by: Yasuaki Ishimatsu <yishimat@redhat.com>
+Acked-by: Minfei Huang <mhuang@redhat.com>
+
+---
+ makedumpfile-1.5.7/makedumpfile.c |  115 +++++++++++++++++++++++++++++++++++-
+ 1 files changed, 111 insertions(+), 4 deletions(-)
+
+diff --git a/makedumpfile-1.5.7/makedumpfile.c b/makedumpfile-1.5.7/makedumpfile.c
+index b4d43d8..141d290 100644
+--- a/makedumpfile-1.5.7/makedumpfile.c
++++ b/makedumpfile-1.5.7/makedumpfile.c
+@@ -24,6 +24,7 @@
+ #include <ctype.h>
+ #include <sys/time.h>
+ #include <limits.h>
++#include <assert.h>
+
+ struct symbol_table	symbol_table;
+ struct size_table	size_table;
+@@ -3768,6 +3769,93 @@ read_flat_data_header(struct makedumpfile_data_header *fdh)
+ }
+
+ int
++reserve_diskspace(int fd, off_t start_offset, off_t end_offset, char *file_name)
++{
++	size_t buf_size;
++	char *buf = NULL;
++
++	int ret = FALSE;
++
++	assert(start_offset < end_offset);
++	buf_size = end_offset - start_offset;
++
++	if ((buf = malloc(buf_size)) == NULL) {
++		ERRMSG("Can't allocate memory for the size of reserved diskspace. %s\n",
++		       strerror(errno));
++		return FALSE;
++	}
++
++	memset(buf, 0, buf_size);
++	if (!write_buffer(fd, start_offset, buf, buf_size, file_name))
++		goto out;
++
++	ret = TRUE;
++out:
++	if (buf != NULL) {
++		free(buf);
++	}
++
++	return ret;
++}
++
++#define DUMP_ELF_INCOMPLETE 0x1
++int
++check_and_modify_elf_headers(char *filename)
++{
++	int fd, ret = FALSE;
++	Elf64_Ehdr ehdr64;
++	Elf32_Ehdr ehdr32;
++
++	if ((fd = open(filename, O_RDWR)) < 0) {
++		ERRMSG("Can't open the dump file(%s). %s\n",
++		       filename, strerror(errno));
++		return FALSE;
++	}
++
++	/*
++	 * the is_elf64_memory() function still can be used.
++	 */
++	/*
++	 * Set the incomplete flag to the e_flags of elf header.
++	 */
++	if (is_elf64_memory()) { /* ELF64 */
++		if (!get_elf64_ehdr(fd, filename, &ehdr64)) {
++			ERRMSG("Can't get ehdr64.\n");
++			goto out_close_file;
++		}
++		ehdr64.e_flags |= DUMP_ELF_INCOMPLETE;
++		if (!write_buffer(fd, 0, &ehdr64, sizeof(Elf64_Ehdr), filename))
++			goto out_close_file;
++
++	} else { /* ELF32 */
++		if (!get_elf32_ehdr(fd, filename, &ehdr32)) {
++			ERRMSG("Can't get ehdr32.\n");
++			goto out_close_file;
++		}
++		ehdr32.e_flags |= DUMP_ELF_INCOMPLETE;
++		if (!write_buffer(fd, 0, &ehdr32, sizeof(Elf32_Ehdr), filename))
++			goto out_close_file;
++
++	}
++	ret = TRUE;
++out_close_file:
++	if (close(fd) < 0) {
++		ERRMSG("Can't close the dump file(%s). %s\n",
++		       filename, strerror(errno));
++	}
++	return ret;
++}
++
++int
++check_and_modify_headers()
++{
++	if (info->flag_elf_dumpfile)
++		return check_and_modify_elf_headers(info->name_dumpfile);
++	return FALSE;
++}
++
++
++int
+ rearrange_dumpdata(void)
+ {
+ 	int read_size, tmp_read_size;
+@@ -5498,6 +5586,13 @@ write_elf_header(struct cache_data *cd_header)
+ 	size_note          = note.p_filesz;
+
+ 	/*
++	 * Reserve a space to store the whole program headers.
++	 */
++	if (!reserve_diskspace(cd_header->fd, cd_header->offset,
++				offset_note_dumpfile, cd_header->file_name))
++		goto out;
++
++	/*
+ 	 * Modify the note size in PT_NOTE header to accomodate eraseinfo data.
+ 	 * Eraseinfo will be written later.
+ 	 */
+@@ -8015,10 +8110,10 @@ writeout_dumpfile(void)
+ 			goto out;
+ 		if (info->flag_cyclic) {
+ 			if (!write_elf_pages_cyclic(&cd_header, &cd_page))
+-				goto out;
++				goto write_cache_enospc;
+ 		} else {
+ 			if (!write_elf_pages(&cd_header, &cd_page))
+-				goto out;
++				goto write_cache_enospc;
+ 		}
+ 		if (!write_elf_eraseinfo(&cd_header))
+ 			goto out;
+@@ -8045,6 +8140,11 @@ writeout_dumpfile(void)
+ 	}
+
+ 	ret = TRUE;
++write_cache_enospc:
++	if ((ret == FALSE) && info->flag_nospace && !info->flag_flatten) {
++		if (!write_cache_bufsz(&cd_header))
++			ERRMSG("This dumpfile may lost some important data.\n");
++	}
+ out:
+ 	free_cache_data(&cd_header);
+ 	free_cache_data(&cd_page);
+@@ -8237,8 +8337,15 @@ retry:
+ 		 * to create a dumpfile with it again.
+ 		 */
+ 		num_retry++;
+-		if ((info->dump_level = get_next_dump_level(num_retry)) < 0)
+- 			return FALSE;
++		if ((info->dump_level = get_next_dump_level(num_retry)) < 0) {
++			if (!info->flag_flatten) {
++				if (check_and_modify_headers())
++					MSG("This is an incomplete dumpfile,"
++						" but might analyzable.\n");
++			}
++
++			return FALSE;
++		}
+ 		MSG("Retry to create a dumpfile by dump_level(%d).\n",
+ 		    info->dump_level);
+ 		if (!delete_dumpfile())
+-- 
+1.7.1
+
diff --git a/SOURCES/kexec-tools-2.0.8-ppc64-erase-unnecessary-segment-info-printing.patch b/SOURCES/kexec-tools-2.0.8-ppc64-erase-unnecessary-segment-info-printing.patch
new file mode 100644
index 0000000..8f6a286
--- /dev/null
+++ b/SOURCES/kexec-tools-2.0.8-ppc64-erase-unnecessary-segment-info-printing.patch
@@ -0,0 +1,30 @@
+In ppc64 loading, it will print the segment information. This is not
+wanted since other Archs don't have this. People even think there's
+something wrong. So erase it to make it be consistent with other Archs.
+
+And if people really want to check these info, they can specify "-d"
+option. They are printed in print_segments() too.
+
+Signed-off-by: Baoquan He <bhe at redhat.com>
+---
+ kexec/arch/ppc64/kexec-elf-ppc64.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
+index ce10367..4a1540e 100644
+--- a/kexec/arch/ppc64/kexec-elf-ppc64.c
++++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
+@@ -377,10 +377,6 @@ int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
+ 	dbgprintf("opal_base is %llx\n", (unsigned long long) my_opal_base);
+ 	dbgprintf("opal_entry is %llx\n", (unsigned long long) my_opal_entry);
+ 
+-	for (i = 0; i < info->nr_segments; i++)
+-		fprintf(stderr, "segment[%d].mem:%p memsz:%zu\n", i,
+-			info->segment[i].mem, info->segment[i].memsz);
+-
+ 	return 0;
+ }
+ 
+-- 
+1.9.0
+
diff --git a/SOURCES/mkdumprd b/SOURCES/mkdumprd
index 8297600..dd6ce8a 100644
--- a/SOURCES/mkdumprd
+++ b/SOURCES/mkdumprd
@@ -17,7 +17,7 @@ SAVE_PATH=$(grep ^path $conf_file| cut -d' '  -f2)
 SAVE_PATH=$(echo $SAVE_PATH | tr -s /)
 
 extra_modules=""
-dracut_args=("--hostonly" "--hostonly-cmdline" "-o" "plymouth dash resume")
+dracut_args=("--hostonly" "--hostonly-cmdline" "--hostonly-i18n" "-o" "plymouth dash resume ifcfg")
 OVERRIDE_RESETTABLE=0
 
 perror_exit() {
@@ -117,6 +117,9 @@ to_mount() {
     _fstype=$(findmnt -k -f -n -r -o FSTYPE $_dev)
     _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/noauto//')
     _options=${_options/#ro/rw} #mount fs target as rw in 2nd kernel
     # "x-initrd.mount" mount failure will trigger isolate emergency service
     # W/o this, systemd won't isolate, thus we won't get to emergency.
diff --git a/SPECS/kexec-tools.spec b/SPECS/kexec-tools.spec
index 16112e7..f12a449 100644
--- a/SPECS/kexec-tools.spec
+++ b/SPECS/kexec-tools.spec
@@ -1,6 +1,6 @@
 Name: kexec-tools
 Version: 2.0.7
-Release: 19%{?dist}.2
+Release: 38%{?dist}
 License: GPLv2
 Group: Applications/System
 Summary: The kexec/kdump userspace component.
@@ -20,14 +20,16 @@ Source14: 98-kexec.rules
 Source15: kdump.conf.5
 Source16: kdump.service
 Source18: kdump.sysconfig.s390x
-Source19: eppic_030413.tar.gz
+Source19: eppic_050615.tar.gz
 Source20: kdump-lib.sh
 Source21: kdump-in-cluster-environment.txt
 Source22: supported-kdump-targets.txt
 Source23: kdump-dep-generator.sh
 Source24: kdump-lib-initramfs.sh
-Source25: kdump-anaconda-addon-003-11-g7f70211.tar.gz
+Source25: kdump-anaconda-addon-003-19-gda64a86.tar.gz
 Source26: kdump.sysconfig.ppc64le
+Source27: kdump.sysconfig.aarch64
+Source28: kdumpctl.8
 
 #######################################
 # These are sources for mkdumpramfs
@@ -45,17 +47,15 @@ Requires(post): systemd-units
 Requires(preun): systemd-units
 Requires(postun): systemd-units
 Requires(pre): coreutils sed zlib 
-Requires: dracut >= 033-145
+Requires: dracut >= 033-346
 Requires: dracut-network, ethtool
 BuildRequires: zlib-devel zlib zlib-static elfutils-devel-static glib2-devel bzip2-devel ncurses-devel bison flex lzo-devel snappy-devel
 BuildRequires: pkgconfig intltool gettext 
 BuildRequires: systemd-units
-%ifarch %{ix86} x86_64 ppc64 ia64 ppc s390x ppc64le
+%ifarch %{ix86} x86_64 ppc64 ia64 ppc s390x ppc64le aarch64
 Obsoletes: diskdumputils netdump
 %endif
 
-ExcludeArch: aarch64
-
 
 #START INSERT
 
@@ -78,6 +78,7 @@ Patch101: kexec-tools-2.0.7-Provide-an-option-to-use-new-kexec-system-call.patch
 Patch301: kexec-tools-2.0.7-kexec-ppc64-disabling-exception-handling-when-buildi.patch
 Patch302: kexec-tools-2.0.7-kexec-ppc64-move-to-device-tree-version-17.patch
 Patch303: kexec-tools-2.0.7-ppc64-kdump-Fix-ELF-header-endianess.patch
+Patch304: kexec-tools-2.0.8-ppc64-erase-unnecessary-segment-info-printing.patch
 
 #
 # Patches 401 through 500 are meant for s390 kexec-tools enablement
@@ -91,6 +92,39 @@ Patch303: kexec-tools-2.0.7-ppc64-kdump-Fix-ELF-header-endianess.patch
 #
 Patch601: kexec-tools-2.0.3-disable-kexec-test.patch
 Patch602: kexec-tools-2.0.7-makedumpfile-sadump-Support-more-than-16TB-physical-memory.patch
+Patch603: kexec-tools-2.0.7-makedumpfile-Support-ARM64.patch
+
+Patch650: kexec-tools-2.0.8-add-aarch64-to-configure.patch
+Patch651: kexec-tools-2.0.8-kexec-Add-common-device-tree-routines.patch
+Patch652: kexec-tools-2.0.8-arm64-Add-arm64-kexec-support.patch
+Patch653: kexec-tools-2.0.8-arm64-Add-support-for-reuse-cmdline-option.patch
+Patch654: kexec-tools-2.0.8-arm64-Add-support-for-kexec-lite-option.patch
+Patch655: kexec-tools-2.0.8-arm64-Kexec-Add-support-for-binary-image.patch
+Patch656: kexec-tools-2.0.8-bugfix-calc-correct-end-address-of-memory-ranges-in-.patch
+Patch657: kexec-tools-2.0.8-arm64-fix-elf-related-header-issues.patch
+Patch658: kexec-tools-2.0.8-arm64-kdump-create-elf-core-header.patch
+Patch659: kexec-tools-2.0.8-arm64-kdump-append-kdump-specific-parameter-to-comma.patch
+Patch660: kexec-tools-2.0.8-arm64-kdump-copy-dtb-file-into-crash-kernel-memory.patch
+Patch661: kexec-tools-2.0.8-arm64-pass-mem-parameter-to-a-crash-dump-kernel.patch
+Patch662: kexec-tools-2.0.8-arm64-clean-up-on-crash-dump.patch
+Patch663: kexec-tools-2.0.8-arm64-remove-restriction-on-the-segments-order.patch
+Patch664: kexec-tools-2.0.8-arm64-kdump-Add-support-for-binary-image.patch
+Patch665: kexec-tools-2.0.8-arm64-wait-for-transmit-completion-before-next-chara.patch
+Patch667: kexec-tools-2.0.8-Don-t-bail-out-if-check_cpu_nodes-fails.patch
+Patch668: kexec-tools-2.0.8-arm64-Add-enable-disable-d-cache-support-for-purgato.patch
+Patch669: kexec-tools-2.0.8-arm64-Pass-RAM-boundary-to-purgatory.patch
+Patch670: kexec-tools-2.0.8-arm64-Enable-disable-D-cache-before-after-sha-verifi.patch
+
+Patch671: kexec-tools-2.0.8-makedumpfile-Make-get_elf64_phdr-get_elf32_phdr-publ.patch
+Patch672: kexec-tools-2.0.8-makedumpfile-Make-the-incomplete-dumpfile-generated-.patch
+Patch673: kexec-tools-2.0.8-makedumpfile-Implementation-of-dealing-with-kdump-co.patch
+Patch674: kexec-tools-2.0.8-makedumpfile-Fix-reassemble_kdump_header.patch
+
+Patch675: kexec-tools-2.0.8-makedumpfile-Add-support-for-splitblock.patch
+Patch676: kexec-tools-2.0.8-makedumpfile-Add-tools-for-reading-and-writing-from-.patch
+Patch677: kexec-tools-2.0.8-makedumpfile-Add-module-of-generating-table.patch
+Patch678: kexec-tools-2.0.8-makedumpfile-Add-module-of-calculating-start_pfn-and.patch
+Patch679: kexec-tools-2.0.8-makedumpfile-Add-support-for-splitblock-size.patch
 
 #
 # Patch 701 through 800 are meant for kdump anaconda addon
@@ -103,7 +137,7 @@ normal or a panic reboot. This package contains the /sbin/kexec
 binary and ancillary utilities that together form the userspace
 component of the kernel's kexec feature.
 
-%ifarch %{ix86} x86_64 ia64 ppc64 s390x ppc64le
+%ifarch %{ix86} x86_64 ia64 ppc64 s390x ppc64le aarch64
 %package eppic
 Requires: %{name} = %{version}-%{release}
 Summary: Additional eppic_makedumpfile.so shared object
@@ -134,8 +168,39 @@ tar -z -x -v -f %{SOURCE25}
 %patch301 -p1
 %patch302 -p1
 %patch303 -p1
+%patch304 -p1
 %patch601 -p1
 %patch602 -p1
+%patch603 -p1
+%patch650 -p1
+%patch651 -p1
+%patch652 -p1
+%patch653 -p1
+%patch654 -p1
+%patch655 -p1
+%patch656 -p1
+%patch657 -p1
+%patch658 -p1
+%patch659 -p1
+%patch660 -p1
+%patch661 -p1
+%patch662 -p1
+%patch663 -p1
+%patch664 -p1
+%patch665 -p1
+%patch667 -p1
+%patch668 -p1
+%patch669 -p1
+%patch670 -p1
+%patch671 -p1
+%patch672 -p1
+%patch673 -p1
+%patch674 -p1
+%patch675 -p1
+%patch676 -p1
+%patch677 -p1
+%patch678 -p1
+%patch679 -p1
 
 
 %ifarch ppc
@@ -143,12 +208,13 @@ tar -z -x -v -f %{SOURCE25}
 %endif
 
 %build
-%ifarch ia64
+%ifarch ia64 aarch64
 # ia64 gcc seems to have a problem adding -fexception -fstack-protect and
-# -param ssp-protect-size, like the %configure macro does
+# -param ssp-protect-size, like the configure macro does
 # while that shouldn't be a problem, and it still builds fine, it results in
 # the kdump kernel hanging on kexec boot.  I don't yet know why, but since those
 # options aren't critical, I'm just overrideing them here for ia64
+# aarch64 does not like -fexception as well, so overwrite it.
 export CFLAGS="-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2"
 %endif
 
@@ -169,7 +235,7 @@ cp %{SOURCE21} .
 cp %{SOURCE22} . 
 
 make
-%ifarch %{ix86} x86_64 ia64 ppc64 s390x ppc64le
+%ifarch %{ix86} x86_64 ia64 ppc64 s390x ppc64le aarch64
 make -C eppic/libeppic
 make -C makedumpfile-1.5.7 LINKTYPE=dynamic USELZO=on USESNAPPY=on
 make -C makedumpfile-1.5.7 LDFLAGS="-I../eppic/libeppic -L../eppic/libeppic" eppic_makedumpfile.so
@@ -200,6 +266,7 @@ install -m 755 %{SOURCE7} $RPM_BUILD_ROOT/sbin/mkdumprd
 install -m 644 %{SOURCE8} $RPM_BUILD_ROOT%{_sysconfdir}/kdump.conf
 install -m 644 kexec/kexec.8 $RPM_BUILD_ROOT%{_mandir}/man8/kexec.8
 install -m 644 %{SOURCE12} $RPM_BUILD_ROOT%{_mandir}/man8/mkdumprd.8
+install -m 644 %{SOURCE28} $RPM_BUILD_ROOT%{_mandir}/man8/kdumpctl.8
 install -m 755 %{SOURCE20} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-lib.sh
 install -m 755 %{SOURCE24} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-lib-initramfs.sh
 %ifnarch s390x
@@ -211,7 +278,7 @@ install -m 644 %{SOURCE15} $RPM_BUILD_ROOT%{_mandir}/man5/kdump.conf.5
 install -m 644 %{SOURCE16} $RPM_BUILD_ROOT%{_unitdir}/kdump.service
 install -m 755 -D %{SOURCE23} $RPM_BUILD_ROOT%{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh
 
-%ifarch %{ix86} x86_64 ia64 ppc64 s390x ppc64le
+%ifarch %{ix86} x86_64 ia64 ppc64 s390x ppc64le aarch64
 install -m 755 makedumpfile-1.5.7/makedumpfile $RPM_BUILD_ROOT/sbin/makedumpfile
 install -m 644 makedumpfile-1.5.7/makedumpfile.8.gz $RPM_BUILD_ROOT/%{_mandir}/man8/makedumpfile.8.gz
 install -m 644 makedumpfile-1.5.7/makedumpfile.conf.5.gz $RPM_BUILD_ROOT/%{_mandir}/man5/makedumpfile.conf.5.gz
@@ -323,7 +390,7 @@ done
 %{_bindir}/*
 %{_datadir}/kdump
 %{_prefix}/lib/kdump
-%ifarch %{ix86} x86_64 ia64 ppc64 s390x ppc64le
+%ifarch %{ix86} x86_64 ia64 ppc64 s390x ppc64le aarch64
 %{_sysconfdir}/makedumpfile.conf.sample
 %endif
 %config(noreplace,missingok) %{_sysconfdir}/sysconfig/kdump
@@ -344,7 +411,7 @@ done
 %doc kdump-in-cluster-environment.txt
 %doc supported-kdump-targets.txt
 
-%ifarch %{ix86} x86_64 ia64 ppc64 s390x ppc64le
+%ifarch %{ix86} x86_64 ia64 ppc64 s390x ppc64le aarch64
 %files eppic
 %{_libdir}/eppic_makedumpfile.so
 /usr/share/makedumpfile/eppic_scripts/
@@ -352,10 +419,74 @@ done
 
 %files anaconda-addon -f kdump-anaconda-addon.lang
 %{_datadir}/anaconda/addons/com_redhat_kdump
+%{_datadir}/icons/hicolor/scalable/apps/kdump.svg
 %doc
 
 %changelog
-* Tue Apr 21 2015 Baoquan He <bhe@redhat.com> - 2.0.7-19.2
+* Wed Oct 21 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-38
+- pc64/ppc64le: drop cpu online rule in 40-redhat.rules in kdump initramfs
+
+* Fri Sep 18 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-37
+- mkdumprd: install only local i18n files
+
+* Wed Sep 9 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-36
+- Update kdump anaconda addon
+
+* Wed Aug 19 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-35
+- kdumpctl: Add man page for kdumpctl
+
+* Fri Aug 14 2015 Baoquan He <bhe@redhat.com> - 2.0.7-34
+arm64: Overwrite CFLAGS and remove -fno-exceptions from kexec purgatory code
+Fix comment to exclude keyword %configure
+Revert "arm64: move -fno-exceptions from purgatory code to spec file"
+
+* Fri Aug 14 2015 Baoquan He <bhe@redhat.com> - 2.0.7-33
+mkdumprd: Remove ifcfg from dracut's modules
+arm64: move -fno-exceptions from purgatory code to spec file
+module-setup: Choose the first matched gateway in kdump_static_ip
+
+* Fri Aug 7 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-32
+- Enhance Kdump to support ipv6 protocol
+
+* Wed Aug 5 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-31
+- ppc64: Erase unnecessary segment info printing
+- Update kdump addon
+
+* Tue Jul 28 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-30
+- watchdog: load iTCO_wdt early in cmdline hook
+
+* Thu Jul 23 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-29
+- Update kdump addon tarball
+
+* Mon Jul 13 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-28
+- eppic: update to include ARM64 support
+- Update kdump addon icon
+
+* Tue Jul 7 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-27
+- dracut-module-setup: Apply the manual DNS to the 2nd kernel
+- makedumpfile: --split: assign fair I/O workloads in appropriate time
+- makedumpfile: Support producing a consistent dump file even if disk space is insufficient
+- Disable transparent hugepages in second kernel
+
+* Tue Jun 23 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-26
+- kdumpctl: Add the command "kdumpctl showmem" to show the reserved memory
+- Enhance kdump.conf "default" parameters check.
+- Filtered out "noauto" options in 2nd kernel fstab
+- make kdump work when kernel crash after shutdown
+
+* Wed Jun 10 2015 Dave Young <dyoung@redhat.com> - 2.0.7-25
+- Update kdump addon tarball
+
+* Mon May 18 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-24
+- Enhance kdump to support ARM64 arch
+
+* Mon May 18 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-23
+- Fix the date for the changelog
+
+* Mon May 18 2015 Minfei Huang <mhuang@redhat.com> - 2.0.7-22
+- remove panic_on_warn from 2nd kernel cmdline
+
+* Tue Apr 21 2015 Baoquan He <bhe@redhat.com> - 2.0.7-21
 - dracut-module-setup: Enhance kdump to support the bind mounted feature in Atomic
 - Fix the warning if the target path is bind mount in Atomic
 - Get the mount point correctly, if the device has several mount point
@@ -363,8 +494,9 @@ done
 - kdump-lib: Add the new function to enhance bind mounted judgement
 - Remove duplicate slash in save path
 - dracut-module-setup.sh: change the insecure use of /tmp/*$$* filenames
+- make kdump saving directory name consistent with RHEL6
 
-* Fri Apr 10 2015 Baoquan He <bhe@redhat.com> - 2.0.7-19.1
+* Thu Apr 09 2015 Baoquan He <bhe@redhat.com> - 2.0.7-20
 - sadump: Support more than 16TB physical memory space.
 
 * Fri Feb 6 2015 Dave Young <dyoung@redhat.com> - 2.0.7-19