From mjaggi at caviumnetworks.com  Mon Oct  3 00:54:34 2016
From: mjaggi at caviumnetworks.com (Manish Jaggi)
Date: Mon, 3 Oct 2016 13:24:34 +0530
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <20160907042908.6232-1-takahiro.akashi@linaro.org>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
Message-ID: <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>

Hi Akashi,

On 09/07/2016 09:59 AM, AKASHI Takahiro wrote:
>     v26-specific note: After a comment from Rob[0], an idea of adding
>     "linux,usable-memory-range" was dropped. Instead, an existing
>     "reserved-memory" node will be used to limit usable memory ranges
>     on crash dump kernel.
>     This works not only on UEFI/ACPI systems but also on DT-only systems,
>     but if he really insists on using DT-specific "usable-memory" property,
>     I will post additional patches for kexec-tools. Those would be
>     redundant, though.
>     Even in that case, the kernel will not have to be changed.
> 
> This patch series adds kdump support on arm64.
> There are some prerequisite patches [1],[2].
> 
> To load a crash-dump kernel to the systems, a series of patches to
> kexec-tools, which have not yet been merged upstream, are needed.
> Please always use my latest kdump patches, v3 [3].
> 
> To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
>   - crash utility (coming v7.1.6 or later) [4]
>     (Necessary patches have already been queued in the master.)
> 
> 
> [0] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/452582.html
> [1] "arm64: mark reserved memblock regions explicitly in iomem"
>     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/450433.html
> [2] "efi: arm64: treat regions with WT/WC set but WB cleared as memory"
>     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/451491.html
> [3] T.B.D.
> [4] https://github.com/crash-utility/crash.git
> 

With the v26 kdump and v3 kexec-tools and top of tree crash.git, below are the tests done
Attached is a patch in crash.git (symbols.c) to make crash utility work on my setup.
Can you please have a look and provide your comments.

To generate a panic, i have a kernel module which on init calls panic.

Observations:
1.1. Dump capture kernel shows different memory map.
---------------------------------------------------
In dump capture kernel /proc/meminfo and /proc/iomem differ

root at arm64:/home/ubuntu/CODE/crash#
MemTotal:       65882432 kB
MemFree:        65507136 kB
MemAvailable:   60373632 kB
Buffers:           29248 kB
Cached:            46720 kB
SwapCached:            0 kB
Active:            63872 kB
Inactive:          19776 kB
Active(anon):       8256 kB
Inactive(anon):     7616 kB

First kernel is booted with mem=2G crashkernel=1G command line option.
While the system has 64G memory.

root at arm64:/home/ubuntu/CODE/crash# cat /proc/iomem
41400000-fffeffff : System RAM
  41480000-420cffff : Kernel code
  42490000-4278ffff : Kernel data
ffff0000-ffffffff : reserved
100000000-ffaa7ffff : System RAM
ffaa80000-ffaabffff : reserved
ffaac0000-fffa6ffff : System RAM
fffa70000-fffacffff : reserved
fffad0000-fffffffff : System RAM

1.2 Live crash dump fails with error
--------------------------------------
$crash vmlinux

crash 7.1.5++
Copyright (C) 2002-2016  Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
Copyright (C) 1999-2006  Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011  NEC Corporation
Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions.  Enter "help copying" to see the conditions.
This program has absolutely no warranty.  Enter "help warranty" for details.

GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "aarch64-unknown-linux-gnu"...

crash: read error: kernel virtual address: ffff800ffffffcc0  type: "pglist node_id"

Observation 2
------------
If saved vmcore file is used

$crash vmlinux vmcore_saved
Got the below error.

please wait... (gathering module symbol data)crash: malloc.c:2846: mremap_chunk: Assertion `((size + offset) & (_rtld_global_ro._dl_pagesize - 1)) == 0' failed.
Aborted

Experiment 3
------------
If crash.git is modified with a hack patch in symbols.c. Crash utility works fine log, bt commands work.
-------------------
Patch: symbols.c
git diff symbols.c
diff --git a/symbols.c b/symbols.c
index 13282f4..f7c6cac 100644
--- a/symbols.c
+++ b/symbols.c
@@ -2160,6 +2160,7 @@ store_module_kallsyms_v2(struct load_module *lm, int start
                 FREEBUF(module_buf);
                 return 0;
         }
+       lm->mod_init_size = 0;

        if (lm->mod_init_size > 0) {
                module_buf_init = GETBUF(lm->mod_init_size);
------------------

$ crash vmlinux vmcore_saved
    KERNEL: /home/ubuntu/CODE/linux/vmlinux
    DUMPFILE: vm
        CPUS: 48 [OFFLINE: 46]
        DATE: Mon Oct  3 00:11:47 2016
      UPTIME: 00:02:41
LOAD AVERAGE: 0.36, 0.14, 0.05
       TASKS: 171
    NODENAME: arm64
     RELEASE: 4.8.0-rc3-00044-g070a615-dirty
     VERSION: #63 SMP Sat Oct 1 01:39:45 PDT 2016
     MACHINE: aarch64  (unknown Mhz)
      MEMORY: 2 GB
       PANIC: "Kernel panic - not syncing: crash module starting"
         PID: 958
     COMMAND: "insmod"
        TASK: ffff800007859300  [THREAD_INFO: ffff80000c940000]
         CPU: 0
       STATE: TASK_RUNNING (PANIC)

crash> bt
PID: 958    TASK: ffff800007859300  CPU: 0   COMMAND: "insmod"
 #0 [ffff80000c943980] __crash_kexec at ffff000008144fe8
 #1 [ffff80000c943ae0] panic at ffff0000081ae704
 #2 [ffff80000c943ba0] init_module at ffff000000900014 [crash]
 #3 [ffff80000c943bb0] do_one_initcall at ffff000008083bb4
 #4 [ffff80000c943c40] do_init_module at ffff0000081af6f0
 #5 [ffff80000c943c70] load_module at ffff000008140b7c
 #6 [ffff80000c943e10] sys_finit_module at ffff000008141634
 #7 [ffff80000c943ed0] el0_svc_naked at ffff0000080833ec
     PC: 00000003  LR: ffffaca050a0  SP: ffffaca865a0  PSTATE: 00000111
    X12: ffffac941a5c X11: 00000080 X10: 00000004  X9: 00000030
     X8: ffffffff  X7: fefefefefefeff40  X6: 00000111  X5: 00000001
     X4: 00000001  X3: 0002ed61  X2: 00000000  X1: 00000003
     X0: 00000000
crash>


---
Thanks,
manish



From takahiro.akashi at linaro.org  Mon Oct  3 04:04:25 2016
From: takahiro.akashi at linaro.org (AKASHI Takahiro)
Date: Mon, 3 Oct 2016 20:04:25 +0900
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
 <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>
Message-ID: <20161003110424.GD14025@linaro.org>

Manish,

On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
> Hi Akashi,
> 
> On 09/07/2016 09:59 AM, AKASHI Takahiro wrote:
> >     v26-specific note: After a comment from Rob[0], an idea of adding
> >     "linux,usable-memory-range" was dropped. Instead, an existing
> >     "reserved-memory" node will be used to limit usable memory ranges
> >     on crash dump kernel.
> >     This works not only on UEFI/ACPI systems but also on DT-only systems,
> >     but if he really insists on using DT-specific "usable-memory" property,
> >     I will post additional patches for kexec-tools. Those would be
> >     redundant, though.
> >     Even in that case, the kernel will not have to be changed.
> > 
> > This patch series adds kdump support on arm64.
> > There are some prerequisite patches [1],[2].
> > 
> > To load a crash-dump kernel to the systems, a series of patches to
> > kexec-tools, which have not yet been merged upstream, are needed.
> > Please always use my latest kdump patches, v3 [3].
> > 
> > To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
> >   - crash utility (coming v7.1.6 or later) [4]
> >     (Necessary patches have already been queued in the master.)
> > 
> > 
> > [0] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/452582.html
> > [1] "arm64: mark reserved memblock regions explicitly in iomem"
> >     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/450433.html
> > [2] "efi: arm64: treat regions with WT/WC set but WB cleared as memory"
> >     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/451491.html
> > [3] T.B.D.
> > [4] https://github.com/crash-utility/crash.git
> > 
> 
> With the v26 kdump and v3 kexec-tools and top of tree crash.git, below are the tests done
> Attached is a patch in crash.git (symbols.c) to make crash utility work on my setup.
> Can you please have a look and provide your comments.
> 
> To generate a panic, i have a kernel module which on init calls panic.
> 
> Observations:
> 1.1. Dump capture kernel shows different memory map.
> ---------------------------------------------------
> In dump capture kernel /proc/meminfo and /proc/iomem differ
> 
> root at arm64:/home/ubuntu/CODE/crash#
> MemTotal:       65882432 kB
> MemFree:        65507136 kB
> MemAvailable:   60373632 kB
> Buffers:           29248 kB
> Cached:            46720 kB
> SwapCached:            0 kB
> Active:            63872 kB
> Inactive:          19776 kB
> Active(anon):       8256 kB
> Inactive(anon):     7616 kB
> 
> First kernel is booted with mem=2G crashkernel=1G command line option.
> While the system has 64G memory.
> 
> root at arm64:/home/ubuntu/CODE/crash# cat /proc/iomem
> 41400000-fffeffff : System RAM
>   41480000-420cffff : Kernel code
>   42490000-4278ffff : Kernel data
> ffff0000-ffffffff : reserved
> 100000000-ffaa7ffff : System RAM
> ffaa80000-ffaabffff : reserved
> ffaac0000-fffa6ffff : System RAM
> fffa70000-fffacffff : reserved
> fffad0000-fffffffff : System RAM

Are you saying that "mem=..." doesn't have any effect?
What about if you don't specify "crashkernel=...?"

> 1.2 Live crash dump fails with error
> --------------------------------------
> $crash vmlinux
> 
> crash 7.1.5++
> Copyright (C) 2002-2016  Red Hat, Inc.
> Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
> Copyright (C) 1999-2006  Hewlett-Packard Co
> Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
> Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
> Copyright (C) 2005, 2011  NEC Corporation
> Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
> Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
> This program is free software, covered by the GNU General Public License,
> and you are welcome to change it and/or distribute copies of it under
> certain conditions.  Enter "help copying" to see the conditions.
> This program has absolutely no warranty.  Enter "help warranty" for details.
> 
> GNU gdb (GDB) 7.6
> Copyright (C) 2013 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "aarch64-unknown-linux-gnu"...
> 
> crash: read error: kernel virtual address: ffff800ffffffcc0  type: "pglist node_id"

I have no ideas here.

> Observation 2
> ------------
> If saved vmcore file is used
> 
> $crash vmlinux vmcore_saved
> Got the below error.
> 
> please wait... (gathering module symbol data)crash: malloc.c:2846: mremap_chunk: Assertion `((size + offset) & (_rtld_global_ro._dl_pagesize - 1)) == 0' failed.
> Aborted

I have no ideas here.

> Experiment 3
> ------------
> If crash.git is modified with a hack patch in symbols.c. Crash utility works fine log, bt commands work.

In which case, "crash vmlinux" or "crash vmlinux vmcore_saved?"

I was able to reproduce this issue in the latter case
(but with a different error message).
It seems to be a crash util's bug.
Please report it to crash-util mailing list.
I will post a patch.

Thanks,
-Takahiro AKASHI

> -------------------
> Patch: symbols.c
> git diff symbols.c
> diff --git a/symbols.c b/symbols.c
> index 13282f4..f7c6cac 100644
> --- a/symbols.c
> +++ b/symbols.c
> @@ -2160,6 +2160,7 @@ store_module_kallsyms_v2(struct load_module *lm, int start
>                  FREEBUF(module_buf);
>                  return 0;
>          }
> +       lm->mod_init_size = 0;
> 
>         if (lm->mod_init_size > 0) {
>                 module_buf_init = GETBUF(lm->mod_init_size);
> ------------------
> 
> $ crash vmlinux vmcore_saved
>     KERNEL: /home/ubuntu/CODE/linux/vmlinux
>     DUMPFILE: vm
>         CPUS: 48 [OFFLINE: 46]
>         DATE: Mon Oct  3 00:11:47 2016
>       UPTIME: 00:02:41
> LOAD AVERAGE: 0.36, 0.14, 0.05
>        TASKS: 171
>     NODENAME: arm64
>      RELEASE: 4.8.0-rc3-00044-g070a615-dirty
>      VERSION: #63 SMP Sat Oct 1 01:39:45 PDT 2016
>      MACHINE: aarch64  (unknown Mhz)
>       MEMORY: 2 GB
>        PANIC: "Kernel panic - not syncing: crash module starting"
>          PID: 958
>      COMMAND: "insmod"
>         TASK: ffff800007859300  [THREAD_INFO: ffff80000c940000]
>          CPU: 0
>        STATE: TASK_RUNNING (PANIC)
> 
> crash> bt
> PID: 958    TASK: ffff800007859300  CPU: 0   COMMAND: "insmod"
>  #0 [ffff80000c943980] __crash_kexec at ffff000008144fe8
>  #1 [ffff80000c943ae0] panic at ffff0000081ae704
>  #2 [ffff80000c943ba0] init_module at ffff000000900014 [crash]
>  #3 [ffff80000c943bb0] do_one_initcall at ffff000008083bb4
>  #4 [ffff80000c943c40] do_init_module at ffff0000081af6f0
>  #5 [ffff80000c943c70] load_module at ffff000008140b7c
>  #6 [ffff80000c943e10] sys_finit_module at ffff000008141634
>  #7 [ffff80000c943ed0] el0_svc_naked at ffff0000080833ec
>      PC: 00000003  LR: ffffaca050a0  SP: ffffaca865a0  PSTATE: 00000111
>     X12: ffffac941a5c X11: 00000080 X10: 00000004  X9: 00000030
>      X8: ffffffff  X7: fefefefefefeff40  X6: 00000111  X5: 00000001
>      X4: 00000001  X3: 0002ed61  X2: 00000000  X1: 00000003
>      X0: 00000000
> crash>
> 
> 
> ---
> Thanks,
> manish
> 


From mjaggi at caviumnetworks.com  Mon Oct  3 05:41:40 2016
From: mjaggi at caviumnetworks.com (Manish Jaggi)
Date: Mon, 3 Oct 2016 18:11:40 +0530
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <20161003110424.GD14025@linaro.org>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
 <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>
 <20161003110424.GD14025@linaro.org>
Message-ID: <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>



On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
> Manish,
> 
> On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
>> Hi Akashi,
>>
>> On 09/07/2016 09:59 AM, AKASHI Takahiro wrote:
>>>     v26-specific note: After a comment from Rob[0], an idea of adding
>>>     "linux,usable-memory-range" was dropped. Instead, an existing
>>>     "reserved-memory" node will be used to limit usable memory ranges
>>>     on crash dump kernel.
>>>     This works not only on UEFI/ACPI systems but also on DT-only systems,
>>>     but if he really insists on using DT-specific "usable-memory" property,
>>>     I will post additional patches for kexec-tools. Those would be
>>>     redundant, though.
>>>     Even in that case, the kernel will not have to be changed.
>>>
>>> This patch series adds kdump support on arm64.
>>> There are some prerequisite patches [1],[2].
>>>
>>> To load a crash-dump kernel to the systems, a series of patches to
>>> kexec-tools, which have not yet been merged upstream, are needed.
>>> Please always use my latest kdump patches, v3 [3].
>>>
>>> To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
>>>   - crash utility (coming v7.1.6 or later) [4]
>>>     (Necessary patches have already been queued in the master.)
>>>
>>>
>>> [0] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/452582.html
>>> [1] "arm64: mark reserved memblock regions explicitly in iomem"
>>>     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/450433.html
>>> [2] "efi: arm64: treat regions with WT/WC set but WB cleared as memory"
>>>     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/451491.html
>>> [3] T.B.D.
>>> [4] https://github.com/crash-utility/crash.git
>>>
>>
>> With the v26 kdump and v3 kexec-tools and top of tree crash.git, below are the tests done
>> Attached is a patch in crash.git (symbols.c) to make crash utility work on my setup.
>> Can you please have a look and provide your comments.
>>
>> To generate a panic, i have a kernel module which on init calls panic.
>>
>> Observations:
>> 1.1. Dump capture kernel shows different memory map.
>> ---------------------------------------------------
>> In dump capture kernel /proc/meminfo and /proc/iomem differ
>>
>> root at arm64:/home/ubuntu/CODE/crash#
>> MemTotal:       65882432 kB
>> MemFree:        65507136 kB
>> MemAvailable:   60373632 kB
>> Buffers:           29248 kB
>> Cached:            46720 kB
>> SwapCached:            0 kB
>> Active:            63872 kB
>> Inactive:          19776 kB
>> Active(anon):       8256 kB
>> Inactive(anon):     7616 kB
>>
>> First kernel is booted with mem=2G crashkernel=1G command line option.
>> While the system has 64G memory.
>>
>> root at arm64:/home/ubuntu/CODE/crash# cat /proc/iomem
>> 41400000-fffeffff : System RAM
>>   41480000-420cffff : Kernel code
>>   42490000-4278ffff : Kernel data
>> ffff0000-ffffffff : reserved
>> 100000000-ffaa7ffff : System RAM
>> ffaa80000-ffaabffff : reserved
>> ffaac0000-fffa6ffff : System RAM
>> fffa70000-fffacffff : reserved
>> fffad0000-fffffffff : System RAM
> 
> Are you saying that "mem=..." doesn't have any effect?
What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
the memory for second kernel has to be withing the crashkernel size.
As per /proc/iomem System RAM the information is correct, but the /proc/meminfo is showing total memory
much more than the first kernel had in first place.
> What about if you don't specify "crashkernel=...?"
> 
In that case the second kernel will not boot as kexec tools will complain that memory not reserved.
>> 1.2 Live crash dump fails with error
>> --------------------------------------
>> $crash vmlinux
>>
>> crash 7.1.5++
>> Copyright (C) 2002-2016  Red Hat, Inc.
>> Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
>> Copyright (C) 1999-2006  Hewlett-Packard Co
>> Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
>> Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
>> Copyright (C) 2005, 2011  NEC Corporation
>> Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
>> Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
>> This program is free software, covered by the GNU General Public License,
>> and you are welcome to change it and/or distribute copies of it under
>> certain conditions.  Enter "help copying" to see the conditions.
>> This program has absolutely no warranty.  Enter "help warranty" for details.
>>
>> GNU gdb (GDB) 7.6
>> Copyright (C) 2013 Free Software Foundation, Inc.
>> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
>> This is free software: you are free to change and redistribute it.
>> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
>> and "show warranty" for details.
>> This GDB was configured as "aarch64-unknown-linux-gnu"...
>>
>> crash: read error: kernel virtual address: ffff800ffffffcc0  type: "pglist node_id"
> 
> I have no ideas here.
If I run with debug logs phys address accessed is > 64G. (10413ffcc0)
Could be that somehow 64 + 1G + (addr) = 10413ffcc0 and actually addr was required.
addr = 413ffcc0 which seems in line with 424b0c50


Logs:
<read_dev_mem: addr: ffff0000090b3008 paddr: 424b3008 cnt: 8>
node_online_map: [1] -> nodes online: 1
<readmem: ffff0000090b0c50, KVADDR, ""node_data"", 8, (ROE), ffffc330eb00>
<read_dev_mem: addr: ffff0000090b0c50 paddr: 424b0c50 cnt: 8>
<readmem: ffff800ffffffcc0, KVADDR, ""pglist node_id"", 4, (FOE), ffffc330f1e4>
<read_dev_mem: addr: ffff800ffffffcc0 paddr: 10413ffcc0 cnt: 4>
/dev/mem: Bad address
crash: read(/dev/mem, 10413ffcc0, 4): 4294967295 (ffffffff)
crash: read error: kernel virtual address: ffff800ffffffcc0  type: ""pglist node_id""
"
> 
>> Observation 2
>> ------------
>> If saved vmcore file is used
>>
>> $crash vmlinux vmcore_saved
>> Got the below error.
>>
>> please wait... (gathering module symbol data)crash: malloc.c:2846: mremap_chunk: Assertion `((size + offset) & (_rtld_global_ro._dl_pagesize - 1)) == 0' failed.
>> Aborted
> 
> I have no ideas here.
> 
>> Experiment 3
>> ------------
>> If crash.git is modified with a hack patch in symbols.c. Crash utility works fine log, bt commands work.
> 
> In which case, "crash vmlinux" or "crash vmlinux vmcore_saved?"
> 
vmcore_saved
> I was able to reproduce this issue in the latter case
> (but with a different error message).
> It seems to be a crash util's bug.
> Please report it to crash-util mailing list.
> I will post a patch.
The same patch as below ?
Can you please share your patch
> 
> Thanks,
> -Takahiro AKASHI
> 
>> -------------------
>> Patch: symbols.c
>> git diff symbols.c
>> diff --git a/symbols.c b/symbols.c
>> index 13282f4..f7c6cac 100644
>> --- a/symbols.c
>> +++ b/symbols.c
>> @@ -2160,6 +2160,7 @@ store_module_kallsyms_v2(struct load_module *lm, int start
>>                  FREEBUF(module_buf);
>>                  return 0;
>>          }
>> +       lm->mod_init_size = 0;
>>
>>         if (lm->mod_init_size > 0) {
>>                 module_buf_init = GETBUF(lm->mod_init_size);
>> ------------------
>>
>> $ crash vmlinux vmcore_saved
>>     KERNEL: /home/ubuntu/CODE/linux/vmlinux
>>     DUMPFILE: vm
>>         CPUS: 48 [OFFLINE: 46]
>>         DATE: Mon Oct  3 00:11:47 2016
>>       UPTIME: 00:02:41
>> LOAD AVERAGE: 0.36, 0.14, 0.05
>>        TASKS: 171
>>     NODENAME: arm64
>>      RELEASE: 4.8.0-rc3-00044-g070a615-dirty
>>      VERSION: #63 SMP Sat Oct 1 01:39:45 PDT 2016
>>      MACHINE: aarch64  (unknown Mhz)
>>       MEMORY: 2 GB
>>        PANIC: "Kernel panic - not syncing: crash module starting"
>>          PID: 958
>>      COMMAND: "insmod"
>>         TASK: ffff800007859300  [THREAD_INFO: ffff80000c940000]
>>          CPU: 0
>>        STATE: TASK_RUNNING (PANIC)
>>
>> crash> bt
>> PID: 958    TASK: ffff800007859300  CPU: 0   COMMAND: "insmod"
>>  #0 [ffff80000c943980] __crash_kexec at ffff000008144fe8
>>  #1 [ffff80000c943ae0] panic at ffff0000081ae704
>>  #2 [ffff80000c943ba0] init_module at ffff000000900014 [crash]
>>  #3 [ffff80000c943bb0] do_one_initcall at ffff000008083bb4
>>  #4 [ffff80000c943c40] do_init_module at ffff0000081af6f0
>>  #5 [ffff80000c943c70] load_module at ffff000008140b7c
>>  #6 [ffff80000c943e10] sys_finit_module at ffff000008141634
>>  #7 [ffff80000c943ed0] el0_svc_naked at ffff0000080833ec
>>      PC: 00000003  LR: ffffaca050a0  SP: ffffaca865a0  PSTATE: 00000111
>>     X12: ffffac941a5c X11: 00000080 X10: 00000004  X9: 00000030
>>      X8: ffffffff  X7: fefefefefefeff40  X6: 00000111  X5: 00000001
>>      X4: 00000001  X3: 0002ed61  X2: 00000000  X1: 00000003
>>      X0: 00000000
>> crash>
>>
>>
>> ---
>> Thanks,
>> manish
>>


From prarit at redhat.com  Mon Oct  3 10:07:12 2016
From: prarit at redhat.com (Prarit Bhargava)
Date: Mon,  3 Oct 2016 13:07:12 -0400
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
Message-ID: <1475514432-27682-1-git-send-email-prarit@redhat.com>

When kdump'ing on a system that has had a socket (package) physically
hotadded, the following panic is occasionally seen:

BUG: unable to handle kernel paging request at 0000000000841f1f
IP: [<ffffffff81014ec4>] uncore_change_context+0xd4/0x180
PGD 0
Oops: 0000 [#1] SMP
Modules linked in:
CPU: 0 PID: 12 Comm: cpuhp/0 Not tainted 4.8.0-rc8+ #3
Hardware name: FUJITSU PRIMEQUEST 2800E3/D3752, BIOS PRIMEQUEST 2000 Series BIOS Version 01.17 05/16/2016
task: ffff88002daf1680 task.stack: ffff88002dafc000
RIP: 0010:[<ffffffff81014ec4>]  [<ffffffff81014ec4>] uncore_change_context+0xd4/0x180
RSP: 0000:ffff88002daffdc8  EFLAGS: 00010286
RAX: ffff88002c069c00 RBX: 0000000000841f0f RCX: ffffffffffffffff
RDX: 000000000000a020 RSI: 00000000ffffffff RDI: ffffffff81c18fa0
RBP: ffff88002daffe10 R08: 0000000000000000 R09: 0000000000000000
R10: 000000000007fff8 R11: 00000000a585a840 R12: ffff88002c0a4400
R13: 0000000000000000 R14: 0000000000000000 R15: ffffffff81c19a20
FS:  0000000000000000(0000) GS:ffff880032c00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000841f1f CR3: 0000000031c06000 CR4: 00000000003406b0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Stack:
 000000000000a020 ffffffff81c18fa0 ffff88002daf28c0 ffff88002daffdf0
 0000000000000000 0000000000000000 000000000000004a ffffffff81015a60
 0000000000000000 ffff88002daffe30 ffffffff81015acc ffff880032c0dda0
Call Trace:
 [<ffffffff81015a60>] ? uncore_cpu_starting+0x130/0x130
 [<ffffffff81015acc>] uncore_event_cpu_online+0x6c/0x80
 [<ffffffff8108e819>] cpuhp_invoke_callback+0x49/0x100
 [<ffffffff8108ead1>] cpuhp_thread_fun+0x41/0x100
 [<ffffffff810b054f>] smpboot_thread_fn+0x10f/0x160
 [<ffffffff810b0440>] ? sort_range+0x30/0x30
 [<ffffffff810accd8>] kthread+0xd8/0xf0
 [<ffffffff816ff4bf>] ret_from_fork+0x1f/0x40
 [<ffffffff810acc00>] ? kthread_park+0x60/0x60
Code: c8 44 89 73 10 41 83 c5 01 49 81 c4 48 01 00 00 45 3b 6f 0c 7d 21 49 8b 84 24 40 01 00 00 4a 8b 1c 10 48 85 db 74 de 85 c9 79 96 <83> 7b 10 ff 75 63 44 89 73 10 eb ce 48 83 45 c0 08 48 8b 45 c0
RIP  [<ffffffff81014ec4>] uncore_change_context+0xd4/0x180
 RSP <ffff88002daffdc8>
CR2: 0000000000841f1f
---[ end trace 2ce4e89368333d22 ]---
Kernel panic - not syncing: Fatal exception
Rebooting in 10 seconds..
ACPI MEMORY or I/O RESET_REG.

The panic shows what the problem is:

arch/x86/events/intel/uncore.c:
1137 static void uncore_change_type_ctx(struct intel_uncore_type *type, int old_     cpu,
1138                                    int new_cpu)
1139 {
1140         struct intel_uncore_pmu *pmu = type->pmus;
1141         struct intel_uncore_box *box;
1142         int i, pkg;
1143
1144         pkg = topology_logical_package_id(old_cpu < 0 ? new_cpu : old_cpu);
1145         for (i = 0; i < type->num_boxes; i++, pmu++) {
1146                 box = pmu->boxes[pkg];

pmu->boxes[pkg] is garbage because pkg was returned as 0xffff.
topology_logical_package_id() is defined as

|#define topology_logical_package_id(cpu)         (cpu_data(cpu).logical_proc_id

which means that logical_proc_id was not defined.  logical_proc_id is set in
arch/x86/kernel/smpboot.c:topology_update_package_map(), which is called in
arch/x86/kernel/smpboot.c:smp_init_package_map.

smp_init_package_map() was introduced in 1f12e32f4cd5 ("x86/topology:
Create logical package id"), and does

arch/x86/kernel/smpboot.c:
358         for_each_present_cpu(cpu) {
359                 unsigned int apicid = apic->cpu_present_to_apicid(cpu);
360
361                 if (apicid == BAD_APICID || !apic->apic_id_valid(apicid))
362                         continue;
363                 if (!topology_update_package_map(apicid, cpu))
364                         continue;

which means that apic->cpu_present_to_apicid(cpu) is returning BAD_APICID
(experimentally verified that it is not the acpi_id_valid() that is the
problem) so that topology_update_package_map() is not called for the cpu,
and the cpu's pkg value will remain the default value of 0xffff.

Following through function pointers, cpu_present_to_apicid() resolves as
default_cpu_present_to_apicid() which is __default_cpu_present_to_apicid()
for x86_64.

arch/x86/include/asm/apic.h:
605 static inline int __default_cpu_present_to_apicid(int mps_cpu)
606 {
607         if (mps_cpu < nr_cpu_ids && cpu_present(mps_cpu))
608                 return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
609         else
610                 return BAD_APICID;
611 }

The per_cpu field x86_bios_cpu_apicid is set in generic_processor_info().
After verifying that the mps_cpu was 0 and the cpu was in the present
map, the only way that x86_bios_cpu_apicid is BAD_APICID for a valid
cpu is if the cpu initialization function generic_processor_info() was not
called on the cpu.

As part of acpi_boot_init(), the acpi_register_lapic() calls
generic_processor_info() and is called for all APIC entries in the MADT
table. The ACPI 6.0 Specification states that the ACPI X2APIC tables does
not have to update on a cpu hotplug event:

"5.2.12.12 Processor Local x2APIC Structure

OSPM does not expect the information provided in this table to be updated if
the processor information changes during the lifespan of an OS boot."

and that explains why generic_processor_info() was not called on a
hotplugged cpu during the kdump kernel boot.

Hot adding a cpu to a system and testing kdump [1] with

taskset -c {hotadded thread id} echo c > /proc/sysrq-trigger

makes the panic occur 100% of the time.  Targetting a cpu that is present in
the MADT results in a valid kdump 100% of time.  These two combined explain the
occasional nature of the panic.

The boot log also contains evidence that generic_processor_info() wasn't
called on the boot cpu, and that was the problem:

smpboot: weird, boot CPU (#507) not listed by the BIOS

and

APIC: NR_CPUS/possible_cpus limit of 1 almost reached. Keeping one slot for boot cpu.  Processor 1/0x2 ignored.

entries are listed for each cpu but there is no indication that the boot
cpu was enumerated in ACPI.  Adding a debug printk shows num_processors is
0 after the ACPI enumeration is complete.

After the ACPI enumeration is complete, prefill_possible_map() [2] checks
if num_processors is 0 and sets it to 1 to account for a boot cpu that
wasn't enumerated.  However, prefill_possible_map() does not call
generic_processor_info() on the boot cpu which leaves the boot cpu with
partially uninitialized data.

This patch adds the missing generic_processor_info() to
prefill_possible_map() to ensure the initialization of the boot cpu is
correct.  This results in smp_init_package_map() having correct data and
properly setting the package map for the hotplugged boot cpu, which in
turn resolves the kdump kernel panic on physically hotplugged cpus.

[1] This can be simulated in a KVM environment by hot adding a CPU and
using taskset to force the dump on the newly added CPU.
[2] prefill_possible_map() is called before smp_store_boot_cpu_info().
The comment beside the call to smp_store_boot_cpu_info() states that the
completed call results in "Final full version of the data".

Signed-off-by: Prarit Bhargava <prarit at redhat.com>
Fixes: 1f12e32f4cd5 ("x86/topology: Create logical package id")
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Ingo Molnar <mingo at redhat.com>
Cc: "H. Peter Anvin" <hpa at zytor.com>
Cc: x86 at kernel.org
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Len Brown <len.brown at intel.com>
Cc: Borislav Petkov <bp at suse.de>
Cc: Andi Kleen <ak at linux.intel.com>
Cc: Jiri Olsa <jolsa at redhat.com>
Cc: Juergen Gross <jgross at suse.com>
Cc: dyoung at redhat.com
Cc: Eric Biederman <ebiederm at xmission.com>
Cc: kexec at lists.infradead.org
---
 arch/x86/kernel/smpboot.c |   15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 4296beb8fdd3..d1272febc13b 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1406,9 +1406,18 @@ __init void prefill_possible_map(void)
 {
 	int i, possible;
 
-	/* no processor from mptable or madt */
-	if (!num_processors)
-		num_processors = 1;
+	/* No boot processor was found in mptable or ACPI MADT */
+	if (!num_processors) {
+		/* Make sure boot cpu is enumerated */
+		if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
+		    apic->apic_id_valid(boot_cpu_physical_apicid))
+			generic_processor_info(boot_cpu_physical_apicid,
+					apic_version[boot_cpu_physical_apicid]);
+		if (!num_processors) {
+			pr_warn("CPU 0 not enumerated in mptable or ACPI MADT\n");
+			num_processors = 1;
+		}
+	}
 
 	i = setup_max_cpus ?: 1;
 	if (setup_possible_cpus == -1) {
-- 
1.7.9.3



From jolsa at redhat.com  Mon Oct  3 15:22:54 2016
From: jolsa at redhat.com (Jiri Olsa)
Date: Tue, 4 Oct 2016 00:22:54 +0200
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
In-Reply-To: <1475514432-27682-1-git-send-email-prarit@redhat.com>
References: <1475514432-27682-1-git-send-email-prarit@redhat.com>
Message-ID: <20161003222254.GA13651@krava>

On Mon, Oct 03, 2016 at 01:07:12PM -0400, Prarit Bhargava wrote:

SNIP

> 
> This patch adds the missing generic_processor_info() to
> prefill_possible_map() to ensure the initialization of the boot cpu is
> correct.  This results in smp_init_package_map() having correct data and
> properly setting the package map for the hotplugged boot cpu, which in
> turn resolves the kdump kernel panic on physically hotplugged cpus.
> 
> [1] This can be simulated in a KVM environment by hot adding a CPU and
> using taskset to force the dump on the newly added CPU.
> [2] prefill_possible_map() is called before smp_store_boot_cpu_info().
> The comment beside the call to smp_store_boot_cpu_info() states that the
> completed call results in "Final full version of the data".
> 
> Signed-off-by: Prarit Bhargava <prarit at redhat.com>
> Fixes: 1f12e32f4cd5 ("x86/topology: Create logical package id")
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Cc: Ingo Molnar <mingo at redhat.com>
> Cc: "H. Peter Anvin" <hpa at zytor.com>
> Cc: x86 at kernel.org
> Cc: Peter Zijlstra <peterz at infradead.org>
> Cc: Len Brown <len.brown at intel.com>
> Cc: Borislav Petkov <bp at suse.de>
> Cc: Andi Kleen <ak at linux.intel.com>
> Cc: Jiri Olsa <jolsa at redhat.com>
> Cc: Juergen Gross <jgross at suse.com>
> Cc: dyoung at redhat.com
> Cc: Eric Biederman <ebiederm at xmission.com>
> Cc: kexec at lists.infradead.org

Reviewed-by: Jiri Olsa <jolsa at redhat.com>

thanks,
jirka

> ---
>  arch/x86/kernel/smpboot.c |   15 ++++++++++++---
>  1 file changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
> index 4296beb8fdd3..d1272febc13b 100644
> --- a/arch/x86/kernel/smpboot.c
> +++ b/arch/x86/kernel/smpboot.c
> @@ -1406,9 +1406,18 @@ __init void prefill_possible_map(void)
>  {
>  	int i, possible;
>  
> -	/* no processor from mptable or madt */
> -	if (!num_processors)
> -		num_processors = 1;
> +	/* No boot processor was found in mptable or ACPI MADT */
> +	if (!num_processors) {
> +		/* Make sure boot cpu is enumerated */
> +		if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
> +		    apic->apic_id_valid(boot_cpu_physical_apicid))
> +			generic_processor_info(boot_cpu_physical_apicid,
> +					apic_version[boot_cpu_physical_apicid]);
> +		if (!num_processors) {
> +			pr_warn("CPU 0 not enumerated in mptable or ACPI MADT\n");
> +			num_processors = 1;
> +		}
> +	}
>  
>  	i = setup_max_cpus ?: 1;
>  	if (setup_possible_cpus == -1) {
> -- 
> 1.7.9.3
> 


From maddy at linux.vnet.ibm.com  Mon Oct  3 18:37:05 2016
From: maddy at linux.vnet.ibm.com (Madhavan Srinivasan)
Date: Tue,  4 Oct 2016 07:07:05 +0530
Subject: [PATCH v3] kexec/fs2dt: Check for NULL pointer in
 dt_copy_old_root_param()
Message-ID: <1475545025-31977-1-git-send-email-maddy@linux.vnet.ibm.com>

In dt_copy_old_root_param(), FILE * returned
from fopen is not checked for NULL pointer
before passinig to fclose(). This could trigger
a segfault. Patch to fix the same.

Signed-off-by: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>
---
Changelog v2
-Removed redundant check fp

Changelog v1:
- Moved the check right after fopen
 
 kexec/fs2dt.c | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/kexec/fs2dt.c b/kexec/fs2dt.c
index 6ed2399759cf..79aa0f320a5a 100644
--- a/kexec/fs2dt.c
+++ b/kexec/fs2dt.c
@@ -524,19 +524,21 @@ static void dt_copy_old_root_param(void)
 	strcpy(filename, pathname);
 	strcat(filename, "bootargs");
 	fp = fopen(filename, "r");
-	if (fp) {
-		if (getline(&last_cmdline, &len, fp) == -1)
-			die("unable to read %s\n", filename);
-
-		p = strstr(last_cmdline, "root=");
-		if (p) {
-			old_param = strtok(p, " ");
-			len = strlen(local_cmdline);
-			if (len != 0)
-				strcat(local_cmdline, " ");
-			strcat(local_cmdline, old_param);
-		}
+	if (!fp)
+		return;
+
+	if (getline(&last_cmdline, &len, fp) == -1)
+		die("unable to read %s\n", filename);
+
+	p = strstr(last_cmdline, "root=");
+	if (p) {
+		old_param = strtok(p, " ");
+		len = strlen(local_cmdline);
+		if (len != 0)
+			strcat(local_cmdline, " ");
+		strcat(local_cmdline, old_param);
 	}
+
 	if (last_cmdline)
 		free(last_cmdline);
 
-- 
2.7.4



From ats-kumagai at wm.jp.nec.com  Mon Oct  3 18:40:09 2016
From: ats-kumagai at wm.jp.nec.com (Atsushi Kumagai)
Date: Tue, 4 Oct 2016 01:40:09 +0000
Subject: [PATCH 3/3] makedumpfile: Add support for MM randomization
In-Reply-To: <20160930045620.GB9185@x1.redhat.com>
References: <1472460862-29842-1-git-send-email-bhe@redhat.com>
 <1472460862-29842-4-git-send-email-bhe@redhat.com>
 <0910DD04CBD6DE4193FCF86B9C00BE9701E62E28@BPXM01GP.gisp.nec.co.jp>
 <20160930045620.GB9185@x1.redhat.com>
Message-ID: <0910DD04CBD6DE4193FCF86B9C00BE9701E6CE53@BPXM01GP.gisp.nec.co.jp>

>> > 	/*
>> > 	 * On linux-2.6.26, MAX_PHYSMEM_BITS is changed to 44 from 40.
>> >@@ -159,22 +160,13 @@ get_versiondep_info_x86_64(void)
>> > 	else
>> > 		info->max_physmem_bits  = _MAX_PHYSMEM_BITS_2_6_31;
>> >
>> >-	if (info->kernel_version < KERNEL_VERSION(2, 6, 27))
>> >-		info->page_offset = __PAGE_OFFSET_ORIG;
>> >-	else
>> >-		info->page_offset = __PAGE_OFFSET_2_6_27;
>> >+	info->page_offset = NUMBER(page_offset);
>> >
>> >-	if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
>> >-		info->vmalloc_start = VMALLOC_START_ORIG;
>> >-		info->vmalloc_end   = VMALLOC_END_ORIG;
>> >-		info->vmemmap_start = VMEMMAP_START_ORIG;
>> >-		info->vmemmap_end   = VMEMMAP_END_ORIG;
>> >-	} else {
>> >-		info->vmalloc_start = VMALLOC_START_2_6_31;
>> >-		info->vmalloc_end   = VMALLOC_END_2_6_31;
>> >-		info->vmemmap_start = VMEMMAP_START_2_6_31;
>> >-		info->vmemmap_end   = VMEMMAP_END_2_6_31;
>> >-	}
>>
>> These *_END_* are no longer used, it's better to remove the definitions
>> of them.
>
>
>Seems is_vmalloc_addr_x86_64 still needs VMALLOC_END and VMEMMAP_END to
>make a judgement.

Yes, VMALLOC_END and VMEMMAP_END are necessary, but what I mentioned were
VMALLOC_END_ORIG, VMEMMAP_END_ORIG , VMALLOC_END_2_6_31 and VMEMMAP_END_2_6_31.
The symbols were used only to initialize info->vmalloc_end and info->vmemmap_end,
so they will be unnecessary by this patch.

>> >+
>> >+	info->vmalloc_start = NUMBER(vmalloc_start);
>> >+	info->vmalloc_end   = info->vmalloc_start + VMALLOC_SIZE - 1;
>> >+	info->vmemmap_start = NUMBER(vmemmap_start);
>> >+	info->vmemmap_end   = info->vmemmap_start + VMEMMAP_SIZE - 1;

Thanks,
Atsushi Kumagai

>> > 	return TRUE;
>> > }
>> >diff --git a/makedumpfile.c b/makedumpfile.c
>> >index 2713f8a..6b0c6ab 100644
>> >--- a/makedumpfile.c
>> >+++ b/makedumpfile.c
>> >@@ -1985,6 +1985,7 @@ get_value_for_old_linux(void)
>> > 			NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE) =
>> > 			PAGE_BUDDY_MAPCOUNT_VALUE_v2_6_39_to_latest_version;
>> > 	}
>> >+	ERRMSG("info->kernel_version=%d\n", info->kernel_version);
>>
>> Is this just a debug message ?
>
>Yes, sorry for this. Will remove it.
>
>>
>> > #ifdef __x86_64__
>> > 	if (NUMBER(KERNEL_IMAGE_SIZE) == NOT_FOUND_NUMBER) {
>> > 		if (info->kernel_version < KERNEL_VERSION(2, 6, 26))
>> >@@ -1992,6 +1993,26 @@ get_value_for_old_linux(void)
>> > 		else
>> > 			NUMBER(KERNEL_IMAGE_SIZE) = KERNEL_IMAGE_SIZE_2_6_26;
>> > 	}
>> >+	if (NUMBER(page_offset) == NOT_FOUND_NUMBER) {
>> >+		if (info->kernel_version < KERNEL_VERSION(2, 6, 27))
>> >+			NUMBER(page_offset) = __PAGE_OFFSET_ORIG;
>> >+		else
>> >+			NUMBER(page_offset) = __PAGE_OFFSET_2_6_27;
>> >+	}
>> >+	if (NUMBER(vmalloc_start) == NOT_FOUND_NUMBER) {
>> >+		if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
>> >+			NUMBER(vmalloc_start) = VMALLOC_START_ORIG;
>> >+		} else {
>> >+			NUMBER(vmalloc_start) = VMALLOC_START_2_6_31;
>> >+		}
>> >+	}
>> >+	if (NUMBER(vmemmap_start) == NOT_FOUND_NUMBER) {
>> >+		if (info->kernel_version < KERNEL_VERSION(2, 6, 31))
>> >+			NUMBER(vmemmap_start) = VMEMMAP_START_ORIG;
>> >+		else
>> >+			NUMBER(vmemmap_start) = VMEMMAP_START_2_6_31;
>> >+	}
>> >+
>>
>> (I should have said this when you post the early kaslr patch.)
>> This logic is only for x86_64, I don't like to take it out to
>> here(general pass) with #ifdef. Is there any necessity to write
>> this code here ?
>
>Yes, you are right. I plan to put them into get_versiondep_info_x86_64.
>>
>> > #endif
>> > 	if (SIZE(pageflags) == NOT_FOUND_STRUCTURE) {
>> > 		if (info->kernel_version >= KERNEL_VERSION(2, 6, 27))
>> >@@ -2249,6 +2270,9 @@ write_vmcoreinfo_data(void)
>> >
>> > 	WRITE_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE);
>> > 	WRITE_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE);
>> >+	WRITE_NUMBER("PAGE_OFFSET", page_offset);
>> >+	WRITE_NUMBER("VMALLOC_START", vmalloc_start);
>> >+	WRITE_NUMBER("VMEMMAP_START", vmemmap_start);
>> >
>> > 	WRITE_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
>> >
>> >@@ -2595,6 +2619,9 @@ read_vmcoreinfo(void)
>> >
>> > 	READ_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE);
>> > 	READ_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE);
>> >+	READ_NUMBER("PAGE_OFFSET", page_offset);
>> >+	READ_NUMBER("VMALLOC_START", vmalloc_start);
>> >+	READ_NUMBER("VMEMMAP_START", vmemmap_start);
>> >
>> > 	READ_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
>> >
>> >@@ -3826,7 +3853,7 @@ initial(void)
>> > 		debug_info = TRUE;
>> > 	}
>> >
>> >-	info->kernel_version = get_kernel_version(info.release);
>> >+	info->kernel_version = get_kernel_version(info->release);
>>
>> Why don't you write "info->release" in [PATCH 1/3] ?
>Yes, will do.
>
>Thanks for your comments and great suggestions!
>
>Thanks
>Baoquan
>
>_______________________________________________
>kexec mailing list
>kexec at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/kexec


From takahiro.akashi at linaro.org  Mon Oct  3 19:56:58 2016
From: takahiro.akashi at linaro.org (AKASHI Takahiro)
Date: Tue, 4 Oct 2016 11:56:58 +0900
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
 <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>
 <20161003110424.GD14025@linaro.org>
 <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>
Message-ID: <20161004025657.GF14025@linaro.org>

On Mon, Oct 03, 2016 at 06:11:40PM +0530, Manish Jaggi wrote:
> 
> 
> On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
> > Manish,
> > 
> > On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
> >> Hi Akashi,
> >>
> >> On 09/07/2016 09:59 AM, AKASHI Takahiro wrote:
> >>>     v26-specific note: After a comment from Rob[0], an idea of adding
> >>>     "linux,usable-memory-range" was dropped. Instead, an existing
> >>>     "reserved-memory" node will be used to limit usable memory ranges
> >>>     on crash dump kernel.
> >>>     This works not only on UEFI/ACPI systems but also on DT-only systems,
> >>>     but if he really insists on using DT-specific "usable-memory" property,
> >>>     I will post additional patches for kexec-tools. Those would be
> >>>     redundant, though.
> >>>     Even in that case, the kernel will not have to be changed.
> >>>
> >>> This patch series adds kdump support on arm64.
> >>> There are some prerequisite patches [1],[2].
> >>>
> >>> To load a crash-dump kernel to the systems, a series of patches to
> >>> kexec-tools, which have not yet been merged upstream, are needed.
> >>> Please always use my latest kdump patches, v3 [3].
> >>>
> >>> To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
> >>>   - crash utility (coming v7.1.6 or later) [4]
> >>>     (Necessary patches have already been queued in the master.)
> >>>
> >>>
> >>> [0] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/452582.html
> >>> [1] "arm64: mark reserved memblock regions explicitly in iomem"
> >>>     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/450433.html
> >>> [2] "efi: arm64: treat regions with WT/WC set but WB cleared as memory"
> >>>     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/451491.html
> >>> [3] T.B.D.
> >>> [4] https://github.com/crash-utility/crash.git
> >>>
> >>
> >> With the v26 kdump and v3 kexec-tools and top of tree crash.git, below are the tests done
> >> Attached is a patch in crash.git (symbols.c) to make crash utility work on my setup.
> >> Can you please have a look and provide your comments.
> >>
> >> To generate a panic, i have a kernel module which on init calls panic.
> >>
> >> Observations:
> >> 1.1. Dump capture kernel shows different memory map.
> >> ---------------------------------------------------
> >> In dump capture kernel /proc/meminfo and /proc/iomem differ
> >>
> >> root at arm64:/home/ubuntu/CODE/crash#
> >> MemTotal:       65882432 kB
> >> MemFree:        65507136 kB
> >> MemAvailable:   60373632 kB
> >> Buffers:           29248 kB
> >> Cached:            46720 kB
> >> SwapCached:            0 kB
> >> Active:            63872 kB
> >> Inactive:          19776 kB
> >> Active(anon):       8256 kB
> >> Inactive(anon):     7616 kB
> >>
> >> First kernel is booted with mem=2G crashkernel=1G command line option.
> >> While the system has 64G memory.
> >>
> >> root at arm64:/home/ubuntu/CODE/crash# cat /proc/iomem
> >> 41400000-fffeffff : System RAM
> >>   41480000-420cffff : Kernel code
> >>   42490000-4278ffff : Kernel data
> >> ffff0000-ffffffff : reserved
> >> 100000000-ffaa7ffff : System RAM
> >> ffaa80000-ffaabffff : reserved
> >> ffaac0000-fffa6ffff : System RAM
> >> fffa70000-fffacffff : reserved
> >> fffad0000-fffffffff : System RAM
> > 
> > Are you saying that "mem=..." doesn't have any effect?
> What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
> the memory for second kernel has to be withing the crashkernel size.
> As per /proc/iomem System RAM the information is correct, but the /proc/meminfo is showing total memory
> much more than the first kernel had in first place.
> > What about if you don't specify "crashkernel=...?"
> > 
> In that case the second kernel will not boot as kexec tools will complain that memory not reserved.
> >> 1.2 Live crash dump fails with error
> >> --------------------------------------
> >> $crash vmlinux
> >>
> >> crash 7.1.5++
> >> Copyright (C) 2002-2016  Red Hat, Inc.
> >> Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
> >> Copyright (C) 1999-2006  Hewlett-Packard Co
> >> Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
> >> Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
> >> Copyright (C) 2005, 2011  NEC Corporation
> >> Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
> >> Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
> >> This program is free software, covered by the GNU General Public License,
> >> and you are welcome to change it and/or distribute copies of it under
> >> certain conditions.  Enter "help copying" to see the conditions.
> >> This program has absolutely no warranty.  Enter "help warranty" for details.
> >>
> >> GNU gdb (GDB) 7.6
> >> Copyright (C) 2013 Free Software Foundation, Inc.
> >> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
> >> This is free software: you are free to change and redistribute it.
> >> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
> >> and "show warranty" for details.
> >> This GDB was configured as "aarch64-unknown-linux-gnu"...
> >>
> >> crash: read error: kernel virtual address: ffff800ffffffcc0  type: "pglist node_id"
> > 
> > I have no ideas here.
> If I run with debug logs phys address accessed is > 64G. (10413ffcc0)
> Could be that somehow 64 + 1G + (addr) = 10413ffcc0 and actually addr was required.
> addr = 413ffcc0 which seems in line with 424b0c50
> 
> 
> Logs:
> <read_dev_mem: addr: ffff0000090b3008 paddr: 424b3008 cnt: 8>
> node_online_map: [1] -> nodes online: 1
> <readmem: ffff0000090b0c50, KVADDR, ""node_data"", 8, (ROE), ffffc330eb00>
> <read_dev_mem: addr: ffff0000090b0c50 paddr: 424b0c50 cnt: 8>
> <readmem: ffff800ffffffcc0, KVADDR, ""pglist node_id"", 4, (FOE), ffffc330f1e4>
> <read_dev_mem: addr: ffff800ffffffcc0 paddr: 10413ffcc0 cnt: 4>
> /dev/mem: Bad address
> crash: read(/dev/mem, 10413ffcc0, 4): 4294967295 (ffffffff)
> crash: read error: kernel virtual address: ffff800ffffffcc0  type: ""pglist node_id""
> "
> > 
> >> Observation 2
> >> ------------
> >> If saved vmcore file is used
> >>
> >> $crash vmlinux vmcore_saved
> >> Got the below error.
> >>
> >> please wait... (gathering module symbol data)crash: malloc.c:2846: mremap_chunk: Assertion `((size + offset) & (_rtld_global_ro._dl_pagesize - 1)) == 0' failed.
> >> Aborted
> > 
> > I have no ideas here.
> > 
> >> Experiment 3
> >> ------------
> >> If crash.git is modified with a hack patch in symbols.c. Crash utility works fine log, bt commands work.
> > 
> > In which case, "crash vmlinux" or "crash vmlinux vmcore_saved?"
> > 
> vmcore_saved
> > I was able to reproduce this issue in the latter case
> > (but with a different error message).
> > It seems to be a crash util's bug.
> > Please report it to crash-util mailing list.
> > I will post a patch.
> The same patch as below ?

No.

> Can you please share your patch

I submitted a bug fix patch. See:
https://www.redhat.com/archives/crash-utility/2016-October/msg00000.html

-Takahiro AKASHI

> > Thanks,
> > -Takahiro AKASHI
> > 
> >> -------------------
> >> Patch: symbols.c
> >> git diff symbols.c
> >> diff --git a/symbols.c b/symbols.c
> >> index 13282f4..f7c6cac 100644
> >> --- a/symbols.c
> >> +++ b/symbols.c
> >> @@ -2160,6 +2160,7 @@ store_module_kallsyms_v2(struct load_module *lm, int start
> >>                  FREEBUF(module_buf);
> >>                  return 0;
> >>          }
> >> +       lm->mod_init_size = 0;
> >>
> >>         if (lm->mod_init_size > 0) {
> >>                 module_buf_init = GETBUF(lm->mod_init_size);
> >> ------------------
> >>
> >> $ crash vmlinux vmcore_saved
> >>     KERNEL: /home/ubuntu/CODE/linux/vmlinux
> >>     DUMPFILE: vm
> >>         CPUS: 48 [OFFLINE: 46]
> >>         DATE: Mon Oct  3 00:11:47 2016
> >>       UPTIME: 00:02:41
> >> LOAD AVERAGE: 0.36, 0.14, 0.05
> >>        TASKS: 171
> >>     NODENAME: arm64
> >>      RELEASE: 4.8.0-rc3-00044-g070a615-dirty
> >>      VERSION: #63 SMP Sat Oct 1 01:39:45 PDT 2016
> >>      MACHINE: aarch64  (unknown Mhz)
> >>       MEMORY: 2 GB
> >>        PANIC: "Kernel panic - not syncing: crash module starting"
> >>          PID: 958
> >>      COMMAND: "insmod"
> >>         TASK: ffff800007859300  [THREAD_INFO: ffff80000c940000]
> >>          CPU: 0
> >>        STATE: TASK_RUNNING (PANIC)
> >>
> >> crash> bt
> >> PID: 958    TASK: ffff800007859300  CPU: 0   COMMAND: "insmod"
> >>  #0 [ffff80000c943980] __crash_kexec at ffff000008144fe8
> >>  #1 [ffff80000c943ae0] panic at ffff0000081ae704
> >>  #2 [ffff80000c943ba0] init_module at ffff000000900014 [crash]
> >>  #3 [ffff80000c943bb0] do_one_initcall at ffff000008083bb4
> >>  #4 [ffff80000c943c40] do_init_module at ffff0000081af6f0
> >>  #5 [ffff80000c943c70] load_module at ffff000008140b7c
> >>  #6 [ffff80000c943e10] sys_finit_module at ffff000008141634
> >>  #7 [ffff80000c943ed0] el0_svc_naked at ffff0000080833ec
> >>      PC: 00000003  LR: ffffaca050a0  SP: ffffaca865a0  PSTATE: 00000111
> >>     X12: ffffac941a5c X11: 00000080 X10: 00000004  X9: 00000030
> >>      X8: ffffffff  X7: fefefefefefeff40  X6: 00000111  X5: 00000001
> >>      X4: 00000001  X3: 0002ed61  X2: 00000000  X1: 00000003
> >>      X0: 00000000
> >> crash>
> >>
> >>
> >> ---
> >> Thanks,
> >> manish
> >>


From james.morse at arm.com  Tue Oct  4 02:46:27 2016
From: james.morse at arm.com (James Morse)
Date: Tue, 04 Oct 2016 10:46:27 +0100
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
 <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>
 <20161003110424.GD14025@linaro.org>
 <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>
Message-ID: <57F37A73.3030105@arm.com>

Hi Manish,

On 03/10/16 13:41, Manish Jaggi wrote:
> On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
>> On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
>>> With the v26 kdump and v3 kexec-tools and top of tree crash.git, below are the tests done
>>> Attached is a patch in crash.git (symbols.c) to make crash utility work on my setup.
>>> Can you please have a look and provide your comments.
>>>
>>> To generate a panic, i have a kernel module which on init calls panic.

... modules ... I haven't tested that. I bet it causes some problems!
We probably need to include module_alloc_base as an elf note in the vmcore file...


>>> First kernel is booted with mem=2G crashkernel=1G command line option.
>>> While the system has 64G memory.

>> Are you saying that "mem=..." doesn't have any effect?
> What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
> the memory for second kernel has to be withing the crashkernel size.
> As per /proc/iomem System RAM the information is correct, but the /proc/meminfo is showing total memory
> much more than the first kernel had in first place.

So your second crashkernel has 63G of memory? Unless you provide the same 'mem='
to the kdump kernel, this is the expected behaviour. The
DT:/reserved-memory/crash_dump describes the memory not to use.

On your first boot with 'mem=2G' memblock_mem_limit_remove_map() called from
arm64_memblock_init() removed the top 62G of memory. Neither the first kernel
nor kexec-tools know about the top 62G.
When you run kexec-tools, it describes what it sees in /proc/iomem in the
DT:/reserved-memory/crash_dump, which is just the remaining 1G of memory.

When we crash and reboot, the crash kernel discovers all 64G of memory from the
EFI memory map.
kexec-tools described the 1G of memory that the first kernel was using in the
DT:/reserved-memory/crash_dump node, so early_init_fdt_scan_reserved_mem()
reserves the 1G of memory the first kernel used. This leaves us with 63G of memory.

This may change with the next version of kdump if it switches back to using
DT:/chosen/linux,usable-memory-range.
If you need v26 to avoid the top 62G of memory, you need to provide the same
'mem=' to the first and second kernel.


>>> 1.2 Live crash dump fails with error

... do we expect this to work? I don't think it has anything to do with this
series...


Thanks,

James



From mjaggi at caviumnetworks.com  Tue Oct  4 03:05:43 2016
From: mjaggi at caviumnetworks.com (Manish Jaggi)
Date: Tue, 4 Oct 2016 15:35:43 +0530
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <57F37A73.3030105@arm.com>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
 <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>
 <20161003110424.GD14025@linaro.org>
 <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>
 <57F37A73.3030105@arm.com>
Message-ID: <691230c7-051d-afee-9014-d22963a8f045@caviumnetworks.com>



On 10/04/2016 03:16 PM, James Morse wrote:
> Hi Manish,
> 
> On 03/10/16 13:41, Manish Jaggi wrote:
>> On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
>>> On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
>>>> With the v26 kdump and v3 kexec-tools and top of tree crash.git, below are the tests done
>>>> Attached is a patch in crash.git (symbols.c) to make crash utility work on my setup.
>>>> Can you please have a look and provide your comments.
>>>>
>>>> To generate a panic, i have a kernel module which on init calls panic.
> 
> ... modules ... I haven't tested that. I bet it causes some problems!
> We probably need to include module_alloc_base as an elf note in the vmcore file...
> 
> 
>>>> First kernel is booted with mem=2G crashkernel=1G command line option.
>>>> While the system has 64G memory.
> 
>>> Are you saying that "mem=..." doesn't have any effect?
>> What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
>> the memory for second kernel has to be withing the crashkernel size.
>> As per /proc/iomem System RAM the information is correct, but the /proc/meminfo is showing total memory
>> much more than the first kernel had in first place.
> 
> So your second crashkernel has 63G of memory? Unless you provide the same 'mem='
> to the kdump kernel, this is the expected behaviour. The
> DT:/reserved-memory/crash_dump describes the memory not to use.
> 
> On your first boot with 'mem=2G' memblock_mem_limit_remove_map() called from
> arm64_memblock_init() removed the top 62G of memory. Neither the first kernel
> nor kexec-tools know about the top 62G.
> When you run kexec-tools, it describes what it sees in /proc/iomem in the
> DT:/reserved-memory/crash_dump, which is just the remaining 1G of memory.
> 
> When we crash and reboot, the crash kernel discovers all 64G of memory from the
> EFI memory map.
So the iomem and meminfo should be same or different for the second kernel?
Also i assumed that crashkernel=1G should restrict the second kernels to 1G.
This is my understanding from the description. It should not require a second mem= option
> kexec-tools described the 1G of memory that the first kernel was using in the
> DT:/reserved-memory/crash_dump node, so early_init_fdt_scan_reserved_mem()
> reserves the 1G of memory the first kernel used. This leaves us with 63G of memory.
> 
> This may change with the next version of kdump if it switches back to using
> DT:/chosen/linux,usable-memory-range.
> If you need v26 to avoid the top 62G of memory, you need to provide the same
> 'mem=' to the first and second kernel.
If I provide for second kernel, I dont see any prints after Bye.
Have you tired this anytime?
> 
> 
>>>> 1.2 Live crash dump fails with error
> 
> ... do we expect this to work? I don't think it has anything to do with this
> series...
> 
Why it should not?
I saved the vmcore file while in second kernel. Since crash without vmcore file didnt run,
Tried with vmcore file and it worked. Its just that if you want to boot a second kernel
 with read only file system without network live crash dump analysis is handy.
> 
> Thanks,
> 
> James
> 


From mark.rutland at arm.com  Tue Oct  4 03:18:33 2016
From: mark.rutland at arm.com (Mark Rutland)
Date: Tue, 4 Oct 2016 11:18:33 +0100
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
 <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>
 <20161003110424.GD14025@linaro.org>
 <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>
Message-ID: <20161004101833.GB18083@leverpostej>

On Mon, Oct 03, 2016 at 06:11:40PM +0530, Manish Jaggi wrote:
> On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
> > On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
> >> Observations:
> >> 1.1. Dump capture kernel shows different memory map.
> >> ---------------------------------------------------
> >> In dump capture kernel /proc/meminfo and /proc/iomem differ
> >>
> >> root at arm64:/home/ubuntu/CODE/crash#
> >> MemTotal:       65882432 kB
> >> MemFree:        65507136 kB
> >> MemAvailable:   60373632 kB
> >> Buffers:           29248 kB
> >> Cached:            46720 kB
> >> SwapCached:            0 kB
> >> Active:            63872 kB
> >> Inactive:          19776 kB
> >> Active(anon):       8256 kB
> >> Inactive(anon):     7616 kB
> >>
> >> First kernel is booted with mem=2G crashkernel=1G command line option.
> >> While the system has 64G memory.
> >>
> >> root at arm64:/home/ubuntu/CODE/crash# cat /proc/iomem
> >> 41400000-fffeffff : System RAM
> >>   41480000-420cffff : Kernel code
> >>   42490000-4278ffff : Kernel data
> >> ffff0000-ffffffff : reserved
> >> 100000000-ffaa7ffff : System RAM
> >> ffaa80000-ffaabffff : reserved
> >> ffaac0000-fffa6ffff : System RAM
> >> fffa70000-fffacffff : reserved
> >> fffad0000-fffffffff : System RAM
> > 
> > Are you saying that "mem=..." doesn't have any effect?
> What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
> the memory for second kernel has to be withing the crashkernel size.

Please don't try to use mem= to limit the kernel to a specific range of
memory. It's really only there as a tool to test handling of low-memory
situations. 

While it guarantees that at most, the amount requested will be used
(modulo a number of edge cases with reserved memory ranges), it does not
guarantee *which* memory will be used. It is *very* fragile.

Thanks,
Mark.


From james.morse at arm.com  Tue Oct  4 03:53:36 2016
From: james.morse at arm.com (James Morse)
Date: Tue, 04 Oct 2016 11:53:36 +0100
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <691230c7-051d-afee-9014-d22963a8f045@caviumnetworks.com>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
 <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>
 <20161003110424.GD14025@linaro.org>
 <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>
 <57F37A73.3030105@arm.com>
 <691230c7-051d-afee-9014-d22963a8f045@caviumnetworks.com>
Message-ID: <57F38A30.2050200@arm.com>

Hi Manish,

On 04/10/16 11:05, Manish Jaggi wrote:
> On 10/04/2016 03:16 PM, James Morse wrote:
>> On 03/10/16 13:41, Manish Jaggi wrote:
>>> On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
>>>> On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
>>>>> First kernel is booted with mem=2G crashkernel=1G command line option.
>>>>> While the system has 64G memory.
>>
>>>> Are you saying that "mem=..." doesn't have any effect?
>>> What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
>>> the memory for second kernel has to be withing the crashkernel size.
>>> As per /proc/iomem System RAM the information is correct, but the /proc/meminfo is showing total memory
>>> much more than the first kernel had in first place.
>>
>> So your second crashkernel has 63G of memory? Unless you provide the same 'mem='
>> to the kdump kernel, this is the expected behaviour. The
>> DT:/reserved-memory/crash_dump describes the memory not to use.
>>
>> On your first boot with 'mem=2G' memblock_mem_limit_remove_map() called from
>> arm64_memblock_init() removed the top 62G of memory. Neither the first kernel
>> nor kexec-tools know about the top 62G.
>> When you run kexec-tools, it describes what it sees in /proc/iomem in the
>> DT:/reserved-memory/crash_dump, which is just the remaining 1G of memory.
>>
>> When we crash and reboot, the crash kernel discovers all 64G of memory from the
>> EFI memory map.

> So the iomem and meminfo should be same or different for the second kernel?
> Also i assumed that crashkernel=1G should restrict the second kernels to 1G.

Not with v26 of this series. What should it do with the 62G of memory that was
removed by booting with 'mem=2G'? It isn't part of the crashkernel reserved
area, and it isn't part of the vmcore described in elfcorehdr either...


> This is my understanding from the description. It should not require a second mem= option

>> kexec-tools described the 1G of memory that the first kernel was using in the
>> DT:/reserved-memory/crash_dump node, so early_init_fdt_scan_reserved_mem()
>> reserves the 1G of memory the first kernel used. This leaves us with 63G of memory.
>>
>> This may change with the next version of kdump if it switches back to using
>> DT:/chosen/linux,usable-memory-range.
>> If you need v26 to avoid the top 62G of memory, you need to provide the same
>> 'mem=' to the first and second kernel.

> If I provide for second kernel, I dont see any prints after Bye.
> Have you tired this anytime?

Yes, on juno-r1 passing 'mem=2G' to both the first and second kernel causes only
the first 2G of memory to be used with this pattern:
first kernel:		[1G used for linux]	[1G reserved for Crash kernel] 	[6G memory
hidden]
kdump kernel:	[1G vmcore]			[1G used for linux] 			[6G memory hidden]


>>>>> 1.2 Live crash dump fails with error
>>
>> ... do we expect this to work? I don't think it has anything to do with this
>> series...
>>
> Why it should not?
> I saved the vmcore file while in second kernel. Since crash without vmcore file didnt run,
> Tried with vmcore file and it worked. Its just that if you want to boot a second kernel
>  with read only file system without network live crash dump analysis is handy.

Ah, you want to run /usr/bin/crash with the kdump boot of linux. You still need
to tell it where to find the memory image: "crash /path/to/vmlinux /proc/vmcore"
should do the trick.


Thanks,

James



From tglx at linutronix.de  Tue Oct  4 03:58:04 2016
From: tglx at linutronix.de (Thomas Gleixner)
Date: Tue, 4 Oct 2016 12:58:04 +0200 (CEST)
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
In-Reply-To: <1475514432-27682-1-git-send-email-prarit@redhat.com>
References: <1475514432-27682-1-git-send-email-prarit@redhat.com>
Message-ID: <alpine.DEB.2.20.1610041241160.7712@nanos>

On Mon, 3 Oct 2016, Prarit Bhargava wrote:
> BUG: unable to handle kernel paging request at 0000000000841f1f
> IP: [<ffffffff81014ec4>] uncore_change_context+0xd4/0x180
...
>  [<ffffffff81015a60>] ? uncore_cpu_starting+0x130/0x130
>  [<ffffffff81015acc>] uncore_event_cpu_online+0x6c/0x80
>  [<ffffffff8108e819>] cpuhp_invoke_callback+0x49/0x100
>  [<ffffffff8108ead1>] cpuhp_thread_fun+0x41/0x100
>  [<ffffffff810b054f>] smpboot_thread_fn+0x10f/0x160
>  [<ffffffff810b0440>] ? sort_range+0x30/0x30
>  [<ffffffff810accd8>] kthread+0xd8/0xf0
>  [<ffffffff816ff4bf>] ret_from_fork+0x1f/0x40
>  [<ffffffff810acc00>] ? kthread_park+0x60/0x60

> arch/x86/events/intel/uncore.c:
> 1137 static void uncore_change_type_ctx(struct intel_uncore_type *type, int old_     cpu,
> 1138                                    int new_cpu)
> 1139 {
> 1140         struct intel_uncore_pmu *pmu = type->pmus;
> 1141         struct intel_uncore_box *box;
> 1142         int i, pkg;
> 1143
> 1144         pkg = topology_logical_package_id(old_cpu < 0 ? new_cpu : old_cpu);
> 1145         for (i = 0; i < type->num_boxes; i++, pmu++) {
> 1146                 box = pmu->boxes[pkg];
> 
> pmu->boxes[pkg] is garbage because pkg was returned as 0xffff.

And that's what needs to be fixed in the first place.

> This patch adds the missing generic_processor_info() to
> prefill_possible_map() to ensure the initialization of the boot cpu is
> correct. 

> This results in smp_init_package_map() having correct data and
> properly setting the package map for the hotplugged boot cpu, which in
> turn resolves the kdump kernel panic on physically hotplugged cpus.

While it is the right thing to initialize the package map in that case, it
still papers over a robustness issue in the uncore code, which needs to be
fixed first.

> [2] prefill_possible_map() is called before smp_store_boot_cpu_info().
> The comment beside the call to smp_store_boot_cpu_info() states that the
> completed call results in "Final full version of the data".

I'm not sure what that [2] here means and I cannot figure out the meaning
of this sentence either.

This changelog is incomprehensible in general and more a "oh look how I
decoded this problem" report than something which clearly describes the
problem at hand, the root cause and the fix. The latter wants a
understandable explanation why prefill_possible_map() is the right place to
do this.

> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
> index 4296beb8fdd3..d1272febc13b 100644
> --- a/arch/x86/kernel/smpboot.c
> +++ b/arch/x86/kernel/smpboot.c
> @@ -1406,9 +1406,18 @@ __init void prefill_possible_map(void)
>  {
>  	int i, possible;
>  
> -	/* no processor from mptable or madt */
> -	if (!num_processors)
> -		num_processors = 1;
> +	/* No boot processor was found in mptable or ACPI MADT */
> +	if (!num_processors) {
> +		/* Make sure boot cpu is enumerated */
> +		if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
> +		    apic->apic_id_valid(boot_cpu_physical_apicid))
> +			generic_processor_info(boot_cpu_physical_apicid,
> +					apic_version[boot_cpu_physical_apicid]);
> +		if (!num_processors) {
> +			pr_warn("CPU 0 not enumerated in mptable or ACPI MADT\n");
> +			num_processors = 1;

And in this case we end up with the same problem, right?

Thanks,

	tglx


From prarit at redhat.com  Tue Oct  4 05:09:45 2016
From: prarit at redhat.com (Prarit Bhargava)
Date: Tue, 04 Oct 2016 08:09:45 -0400
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
In-Reply-To: <alpine.DEB.2.20.1610041241160.7712@nanos>
References: <1475514432-27682-1-git-send-email-prarit@redhat.com>
 <alpine.DEB.2.20.1610041241160.7712@nanos>
Message-ID: <57F39C09.10001@redhat.com>



On 10/04/2016 06:58 AM, Thomas Gleixner wrote:
> On Mon, 3 Oct 2016, Prarit Bhargava wrote:
>> BUG: unable to handle kernel paging request at 0000000000841f1f
>> IP: [<ffffffff81014ec4>] uncore_change_context+0xd4/0x180
> ...
>>  [<ffffffff81015a60>] ? uncore_cpu_starting+0x130/0x130
>>  [<ffffffff81015acc>] uncore_event_cpu_online+0x6c/0x80
>>  [<ffffffff8108e819>] cpuhp_invoke_callback+0x49/0x100
>>  [<ffffffff8108ead1>] cpuhp_thread_fun+0x41/0x100
>>  [<ffffffff810b054f>] smpboot_thread_fn+0x10f/0x160
>>  [<ffffffff810b0440>] ? sort_range+0x30/0x30
>>  [<ffffffff810accd8>] kthread+0xd8/0xf0
>>  [<ffffffff816ff4bf>] ret_from_fork+0x1f/0x40
>>  [<ffffffff810acc00>] ? kthread_park+0x60/0x60
> 
>> arch/x86/events/intel/uncore.c:
>> 1137 static void uncore_change_type_ctx(struct intel_uncore_type *type, int old_     cpu,
>> 1138                                    int new_cpu)
>> 1139 {
>> 1140         struct intel_uncore_pmu *pmu = type->pmus;
>> 1141         struct intel_uncore_box *box;
>> 1142         int i, pkg;
>> 1143
>> 1144         pkg = topology_logical_package_id(old_cpu < 0 ? new_cpu : old_cpu);
>> 1145         for (i = 0; i < type->num_boxes; i++, pmu++) {
>> 1146                 box = pmu->boxes[pkg];
>>
>> pmu->boxes[pkg] is garbage because pkg was returned as 0xffff.
> 
> And that's what needs to be fixed in the first place.
> 
>> This patch adds the missing generic_processor_info() to
>> prefill_possible_map() to ensure the initialization of the boot cpu is
>> correct. 
> 
>> This results in smp_init_package_map() having correct data and
>> properly setting the package map for the hotplugged boot cpu, which in
>> turn resolves the kdump kernel panic on physically hotplugged cpus.
> 
> While it is the right thing to initialize the package map in that case, it
> still papers over a robustness issue in the uncore code, which needs to be
> fixed first.

I will include a separate patch with an error check for pkg == 0xffff in the
uncore code.

> 
>> [2] prefill_possible_map() is called before smp_store_boot_cpu_info().
>> The comment beside the call to smp_store_boot_cpu_info() states that the
>> completed call results in "Final full version of the data".
> 
> I'm not sure what that [2] here means and I cannot figure out the meaning
> of this sentence either.

My understanding is that after the call to smp_store_boot_cpu_info(), that for
the rest of the initial bringup the cpu_data structs, etc., are complete.

> 
> This changelog is incomprehensible in general and more a "oh look how I
> decoded this problem" report than something which clearly describes the
> problem at hand, the root cause and the fix. 

That wasn't my intention.

I had to figure it out and it took quite a while to get through it.  I had
doubts that all of the others on the cc list would understand this and I
expected questions of "Can you prove that is the case?".

My changelog addresses those expected questions and I have no problem with a
shortened changelog.

The latter wants a
> understandable explanation why prefill_possible_map() is the right place to
> do this.

> 
>> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
>> index 4296beb8fdd3..d1272febc13b 100644
>> --- a/arch/x86/kernel/smpboot.c
>> +++ b/arch/x86/kernel/smpboot.c
>> @@ -1406,9 +1406,18 @@ __init void prefill_possible_map(void)
>>  {
>>  	int i, possible;
>>  
>> -	/* no processor from mptable or madt */
>> -	if (!num_processors)
>> -		num_processors = 1;
>> +	/* No boot processor was found in mptable or ACPI MADT */
>> +	if (!num_processors) {
>> +		/* Make sure boot cpu is enumerated */
>> +		if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
>> +		    apic->apic_id_valid(boot_cpu_physical_apicid))
>> +			generic_processor_info(boot_cpu_physical_apicid,
>> +					apic_version[boot_cpu_physical_apicid]);
>> +		if (!num_processors) {
>> +			pr_warn("CPU 0 not enumerated in mptable or ACPI MADT\n");
>> +			num_processors = 1;
> 
> And in this case we end up with the same problem, right?

It occurs to me that I over thought this: I was thinking that there might exist
a pre-ACPI (or at least a system without an MADT) x86 system that wold boot such
that num_processors = 0.  But in that case, the cpu should be listed in the
mptables so the above should not happen.  I'll change that to a BUG().

P.

> 
> Thanks,
> 
> 	tglx
> 


From jolsa at redhat.com  Tue Oct  4 05:27:17 2016
From: jolsa at redhat.com (Jiri Olsa)
Date: Tue, 4 Oct 2016 14:27:17 +0200
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
In-Reply-To: <alpine.DEB.2.20.1610041241160.7712@nanos>
References: <1475514432-27682-1-git-send-email-prarit@redhat.com>
 <alpine.DEB.2.20.1610041241160.7712@nanos>
Message-ID: <20161004122717.GA4998@krava>

On Tue, Oct 04, 2016 at 12:58:04PM +0200, Thomas Gleixner wrote:
> On Mon, 3 Oct 2016, Prarit Bhargava wrote:
> > BUG: unable to handle kernel paging request at 0000000000841f1f
> > IP: [<ffffffff81014ec4>] uncore_change_context+0xd4/0x180
> ...
> >  [<ffffffff81015a60>] ? uncore_cpu_starting+0x130/0x130
> >  [<ffffffff81015acc>] uncore_event_cpu_online+0x6c/0x80
> >  [<ffffffff8108e819>] cpuhp_invoke_callback+0x49/0x100
> >  [<ffffffff8108ead1>] cpuhp_thread_fun+0x41/0x100
> >  [<ffffffff810b054f>] smpboot_thread_fn+0x10f/0x160
> >  [<ffffffff810b0440>] ? sort_range+0x30/0x30
> >  [<ffffffff810accd8>] kthread+0xd8/0xf0
> >  [<ffffffff816ff4bf>] ret_from_fork+0x1f/0x40
> >  [<ffffffff810acc00>] ? kthread_park+0x60/0x60
> 
> > arch/x86/events/intel/uncore.c:
> > 1137 static void uncore_change_type_ctx(struct intel_uncore_type *type, int old_     cpu,
> > 1138                                    int new_cpu)
> > 1139 {
> > 1140         struct intel_uncore_pmu *pmu = type->pmus;
> > 1141         struct intel_uncore_box *box;
> > 1142         int i, pkg;
> > 1143
> > 1144         pkg = topology_logical_package_id(old_cpu < 0 ? new_cpu : old_cpu);
> > 1145         for (i = 0; i < type->num_boxes; i++, pmu++) {
> > 1146                 box = pmu->boxes[pkg];
> > 
> > pmu->boxes[pkg] is garbage because pkg was returned as 0xffff.
> 
> And that's what needs to be fixed in the first place.

right, I'll check on that.. but I think we need this fix as well

> 
> > This patch adds the missing generic_processor_info() to
> > prefill_possible_map() to ensure the initialization of the boot cpu is
> > correct. 
> 
> > This results in smp_init_package_map() having correct data and
> > properly setting the package map for the hotplugged boot cpu, which in
> > turn resolves the kdump kernel panic on physically hotplugged cpus.
> 
> While it is the right thing to initialize the package map in that case, it
> still papers over a robustness issue in the uncore code, which needs to be
> fixed first.
> 
> > [2] prefill_possible_map() is called before smp_store_boot_cpu_info().
> > The comment beside the call to smp_store_boot_cpu_info() states that the
> > completed call results in "Final full version of the data".
> 
> I'm not sure what that [2] here means and I cannot figure out the meaning
> of this sentence either.
> 
> This changelog is incomprehensible in general and more a "oh look how I
> decoded this problem" report than something which clearly describes the
> problem at hand, the root cause and the fix. The latter wants a
> understandable explanation why prefill_possible_map() is the right place to
> do this.

I was wondering if acpi_boot_init was a better place for that, but then
Prarit suggested in our discussion that the prefill_possible_map() call
seems to be a hotplug cleanup.. so it seemed to fit

however it's difficult to say with complex code like this,
so any ideas are welcome ;-)

thanks,
jirka


From bhe at redhat.com  Tue Oct  4 06:09:49 2016
From: bhe at redhat.com (Baoquan He)
Date: Tue, 4 Oct 2016 21:09:49 +0800
Subject: [PATCH 3/3] makedumpfile: Add support for MM randomization
In-Reply-To: <0910DD04CBD6DE4193FCF86B9C00BE9701E6CE53@BPXM01GP.gisp.nec.co.jp>
References: <1472460862-29842-1-git-send-email-bhe@redhat.com>
 <1472460862-29842-4-git-send-email-bhe@redhat.com>
 <0910DD04CBD6DE4193FCF86B9C00BE9701E62E28@BPXM01GP.gisp.nec.co.jp>
 <20160930045620.GB9185@x1.redhat.com>
 <0910DD04CBD6DE4193FCF86B9C00BE9701E6CE53@BPXM01GP.gisp.nec.co.jp>
Message-ID: <20161004130949.GD9185@x1.redhat.com>

On 10/04/16 at 01:40am, Atsushi Kumagai wrote:
> >> > 	/*
> >> > 	 * On linux-2.6.26, MAX_PHYSMEM_BITS is changed to 44 from 40.
> >> >@@ -159,22 +160,13 @@ get_versiondep_info_x86_64(void)
> >> > 	else
> >> > 		info->max_physmem_bits  = _MAX_PHYSMEM_BITS_2_6_31;
> >> >
> >> >-	if (info->kernel_version < KERNEL_VERSION(2, 6, 27))
> >> >-		info->page_offset = __PAGE_OFFSET_ORIG;
> >> >-	else
> >> >-		info->page_offset = __PAGE_OFFSET_2_6_27;
> >> >+	info->page_offset = NUMBER(page_offset);
> >> >
> >> >-	if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
> >> >-		info->vmalloc_start = VMALLOC_START_ORIG;
> >> >-		info->vmalloc_end   = VMALLOC_END_ORIG;
> >> >-		info->vmemmap_start = VMEMMAP_START_ORIG;
> >> >-		info->vmemmap_end   = VMEMMAP_END_ORIG;
> >> >-	} else {
> >> >-		info->vmalloc_start = VMALLOC_START_2_6_31;
> >> >-		info->vmalloc_end   = VMALLOC_END_2_6_31;
> >> >-		info->vmemmap_start = VMEMMAP_START_2_6_31;
> >> >-		info->vmemmap_end   = VMEMMAP_END_2_6_31;
> >> >-	}
> >>
> >> These *_END_* are no longer used, it's better to remove the definitions
> >> of them.
> >
> >
> >Seems is_vmalloc_addr_x86_64 still needs VMALLOC_END and VMEMMAP_END to
> >make a judgement.
> 
> Yes, VMALLOC_END and VMEMMAP_END are necessary, but what I mentioned were
> VMALLOC_END_ORIG, VMEMMAP_END_ORIG , VMALLOC_END_2_6_31 and VMEMMAP_END_2_6_31.
> The symbols were used only to initialize info->vmalloc_end and info->vmemmap_end,
> so they will be unnecessary by this patch.

Yes, you are right. These unused MACRO definitions need be removed.
Thanks for your reviewing.

Thanks
Baoquan


From mjaggi at caviumnetworks.com  Tue Oct  4 06:23:28 2016
From: mjaggi at caviumnetworks.com (Manish Jaggi)
Date: Tue, 4 Oct 2016 18:53:28 +0530
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <57F38A30.2050200@arm.com>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
 <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>
 <20161003110424.GD14025@linaro.org>
 <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>
 <57F37A73.3030105@arm.com>
 <691230c7-051d-afee-9014-d22963a8f045@caviumnetworks.com>
 <57F38A30.2050200@arm.com>
Message-ID: <70ca1b97-8de4-921f-0cef-e02a88691ccd@caviumnetworks.com>



On 10/04/2016 04:23 PM, James Morse wrote:
> Hi Manish,
> 
> On 04/10/16 11:05, Manish Jaggi wrote:
>> On 10/04/2016 03:16 PM, James Morse wrote:
>>> On 03/10/16 13:41, Manish Jaggi wrote:
>>>> On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
>>>>> On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
>>>>>> First kernel is booted with mem=2G crashkernel=1G command line option.
>>>>>> While the system has 64G memory.
>>>
>>>>> Are you saying that "mem=..." doesn't have any effect?
>>>> What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
>>>> the memory for second kernel has to be withing the crashkernel size.
>>>> As per /proc/iomem System RAM the information is correct, but the /proc/meminfo is showing total memory
>>>> much more than the first kernel had in first place.
>>>
>>> So your second crashkernel has 63G of memory? Unless you provide the same 'mem='
>>> to the kdump kernel, this is the expected behaviour. The
>>> DT:/reserved-memory/crash_dump describes the memory not to use.
>>>
>>> On your first boot with 'mem=2G' memblock_mem_limit_remove_map() called from
>>> arm64_memblock_init() removed the top 62G of memory. Neither the first kernel
>>> nor kexec-tools know about the top 62G.
>>> When you run kexec-tools, it describes what it sees in /proc/iomem in the
>>> DT:/reserved-memory/crash_dump, which is just the remaining 1G of memory.
>>>
>>> When we crash and reboot, the crash kernel discovers all 64G of memory from the
>>> EFI memory map.
> 
>> So the iomem and meminfo should be same or different for the second kernel?
>> Also i assumed that crashkernel=1G should restrict the second kernels to 1G.
> 
> Not with v26 of this series. What should it do with the 62G of memory that was
> removed by booting with 'mem=2G'? It isn't part of the crashkernel reserved
> area, and it isn't part of the vmcore described in elfcorehdr either...
> 
> 
>> This is my understanding from the description. It should not require a second mem= option
> 
>>> kexec-tools described the 1G of memory that the first kernel was using in the
>>> DT:/reserved-memory/crash_dump node, so early_init_fdt_scan_reserved_mem()
>>> reserves the 1G of memory the first kernel used. This leaves us with 63G of memory.
>>>
>>> This may change with the next version of kdump if it switches back to using
>>> DT:/chosen/linux,usable-memory-range.
>>> If you need v26 to avoid the top 62G of memory, you need to provide the same
>>> 'mem=' to the first and second kernel.
> 
>> If I provide for second kernel, I dont see any prints after Bye.
>> Have you tired this anytime?
> 
> Yes, on juno-r1 passing 'mem=2G' to both the first and second kernel causes only
> the first 2G of memory to be used with this pattern:
> first kernel:		[1G used for linux]	[1G reserved for Crash kernel] 	[6G memory
> hidden]
> kdump kernel:	[1G vmcore]			[1G used for linux] 			[6G memory hidden]
> 
> 
Oh, ok!
I was giving mem=1G to crashkernel to test. with mem=2G it works.
>>>>>> 1.2 Live crash dump fails with error
>>>
>>> ... do we expect this to work? I don't think it has anything to do with this
>>> series...
>>>
>> Why it should not?
>> I saved the vmcore file while in second kernel. Since crash without vmcore file didnt run,
>> Tried with vmcore file and it worked. Its just that if you want to boot a second kernel
>>  with read only file system without network live crash dump analysis is handy.
> 
> Ah, you want to run /usr/bin/crash with the kdump boot of linux. You still need
> to tell it where to find the memory image: "crash /path/to/vmlinux /proc/vmcore"
> should do the trick.
> 
We should fix the documentation of kdump them.
Since it is not supported, it should be removed.
> 
> Thanks,
> 
> James
> 


From tglx at linutronix.de  Tue Oct  4 07:19:59 2016
From: tglx at linutronix.de (Thomas Gleixner)
Date: Tue, 4 Oct 2016 16:19:59 +0200 (CEST)
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
In-Reply-To: <20161004122717.GA4998@krava>
References: <1475514432-27682-1-git-send-email-prarit@redhat.com>
 <alpine.DEB.2.20.1610041241160.7712@nanos> <20161004122717.GA4998@krava>
Message-ID: <alpine.DEB.2.20.1610041618390.5049@nanos>

On Tue, 4 Oct 2016, Jiri Olsa wrote:
> On Tue, Oct 04, 2016 at 12:58:04PM +0200, Thomas Gleixner wrote:
> > > pmu->boxes[pkg] is garbage because pkg was returned as 0xffff.
> > 
> > And that's what needs to be fixed in the first place.
> 
> right, I'll check on that.. but I think we need this fix as well

That's right.
 
> I was wondering if acpi_boot_init was a better place for that, but then
> Prarit suggested in our discussion that the prefill_possible_map() call
> seems to be a hotplug cleanup.. so it seemed to fit

It's the right place for it.

Thanks,

	tglx


From tglx at linutronix.de  Tue Oct  4 07:38:16 2016
From: tglx at linutronix.de (Thomas Gleixner)
Date: Tue, 4 Oct 2016 16:38:16 +0200 (CEST)
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
In-Reply-To: <57F39C09.10001@redhat.com>
References: <1475514432-27682-1-git-send-email-prarit@redhat.com>
 <alpine.DEB.2.20.1610041241160.7712@nanos> <57F39C09.10001@redhat.com>
Message-ID: <alpine.DEB.2.20.1610041628120.5049@nanos>

On Tue, 4 Oct 2016, Prarit Bhargava wrote:
> On 10/04/2016 06:58 AM, Thomas Gleixner wrote:
> > While it is the right thing to initialize the package map in that case, it
> > still papers over a robustness issue in the uncore code, which needs to be
> > fixed first.
> 
> I will include a separate patch with an error check for pkg == 0xffff in the
> uncore code.

0xffff? That won't help. The id returned is -1 if the entry is not
initialized. And aside of that just patching that particular place is not
helping as the uncore code and also rapl is relying on the package map
being populated.

So we need a sanity check in the initialization code which prevents any of
this being executed.
 
> >> +		if (!num_processors) {
> >> +			pr_warn("CPU 0 not enumerated in mptable or ACPI MADT\n");
> >> +			num_processors = 1;
> > 
> > And in this case we end up with the same problem, right?
> 
> It occurs to me that I over thought this: I was thinking that there might exist
> a pre-ACPI (or at least a system without an MADT) x86 system that wold boot such
> that num_processors = 0.  But in that case, the cpu should be listed in the
> mptables so the above should not happen.  I'll change that to a BUG().

No. That's the wrong thing to do. Think SMP kernel on UP machines ...

Thanks,

	tglx




From prarit at redhat.com  Tue Oct  4 09:01:24 2016
From: prarit at redhat.com (Prarit Bhargava)
Date: Tue, 04 Oct 2016 12:01:24 -0400
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
In-Reply-To: <alpine.DEB.2.20.1610041628120.5049@nanos>
References: <1475514432-27682-1-git-send-email-prarit@redhat.com>
 <alpine.DEB.2.20.1610041241160.7712@nanos> <57F39C09.10001@redhat.com>
 <alpine.DEB.2.20.1610041628120.5049@nanos>
Message-ID: <57F3D254.20806@redhat.com>



On 10/04/2016 10:38 AM, Thomas Gleixner wrote:
> On Tue, 4 Oct 2016, Prarit Bhargava wrote:
>> On 10/04/2016 06:58 AM, Thomas Gleixner wrote:
>>> While it is the right thing to initialize the package map in that case, it
>>> still papers over a robustness issue in the uncore code, which needs to be
>>> fixed first.
>>
>> I will include a separate patch with an error check for pkg == 0xffff in the
>> uncore code.
> 
> 0xffff? That won't help. The id returned is -1 if the entry is not
> initialized. And aside of that just patching that particular place is not
> helping as the uncore code and also rapl is relying on the package map
> being populated.

Yes, I noticed that after I started digging into it this morning.  Not only what
you pointed out but there's init that occurs in the uncore code that would have
to be undone.

There is a similar issue in the rapl code, but that code inadvertently protects
itself with for loops that end up never running (and that's why the rapl code
doesn't panic).

> 
> So we need a sanity check in the initialization code which prevents any of
> this being executed.

Ok, should this be done only for logical_proc_id or for logical_proc_id,
phys_proc_id, and cpu_core_id?  What do you think of adding that to the end of
smp_init_package_map() or smp_store_cpu_info()?

>  
>>>> +		if (!num_processors) {
>>>> +			pr_warn("CPU 0 not enumerated in mptable or ACPI MADT\n");
>>>> +			num_processors = 1;
>>>
>>> And in this case we end up with the same problem, right?
>>
>> It occurs to me that I over thought this: I was thinking that there might exist
>> a pre-ACPI (or at least a system without an MADT) x86 system that wold boot such
>> that num_processors = 0.  But in that case, the cpu should be listed in the
>> mptables so the above should not happen.  I'll change that to a BUG().
> 
> No. That's the wrong thing to do. Think SMP kernel on UP machines ...
> 

Sorry Thomas, but my history with real UP hardware is limited.  I think you
might be saying I should call generic_processor_info(0, apic_version[0]) to
populate cpu 0 but I'm not sure.

P.


From takahiro.akashi at linaro.org  Tue Oct  4 22:41:12 2016
From: takahiro.akashi at linaro.org (AKASHI Takahiro)
Date: Wed, 5 Oct 2016 14:41:12 +0900
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <57F37A73.3030105@arm.com>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
 <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>
 <20161003110424.GD14025@linaro.org>
 <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>
 <57F37A73.3030105@arm.com>
Message-ID: <20161005054111.GA19531@linaro.org>

On Tue, Oct 04, 2016 at 10:46:27AM +0100, James Morse wrote:
> Hi Manish,
> 
> On 03/10/16 13:41, Manish Jaggi wrote:
> > On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
> >> On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
> >>> With the v26 kdump and v3 kexec-tools and top of tree crash.git, below are the tests done
> >>> Attached is a patch in crash.git (symbols.c) to make crash utility work on my setup.
> >>> Can you please have a look and provide your comments.
> >>>
> >>> To generate a panic, i have a kernel module which on init calls panic.
> 
> ... modules ... I haven't tested that. I bet it causes some problems!
> We probably need to include module_alloc_base as an elf note in the vmcore file...

No, I don't think so :)
I created some test module as Manish implied and tested kdump:
(My kernel here even enables KASLR.)
===8<===
$ crash vmlinux vmcore
...
please wait... (gathering module symbol data)
...
crash> mod -S
     MODULE       NAME      SIZE  OBJECT FILE
ffff04d78f4b8000  testmod  16384  /opt/buildroot/15.11_64/root/kexec/testmod.ko 
crash> bt
PID: 1102   TASK: ffffb4da8e910000  CPU: 0   COMMAND: "insmod"
 #0 [ffffb4da8e9afa30] __crash_kexec at ffff0e0045020a54
 #1 [ffffb4da8e9afb90] panic at ffff0e004505523c
 #2 [ffffb4da8e9afc50] testmod_init at ffff04d78f4b6014 [testmod]
 #3 [ffffb4da8e9afb40] do_one_initcall at ffff0e0044f7333c
--- <Exception in user> ---
     PC: 0000000a  LR: 00000000  SP: ffff04d78f4b6000  PSTATE: 7669726420656c75
    X12: ffffb4da8e9ac000 X11: ffff04d78f4b6018 X10: ffffb4da8e9afc50  X9: 20676e6973756143
     X8: 00000000  X7: ffff0e0045e5ce00  X6: ffff0e0045e5c000  X5: 600001c5
     X4: ffff0e0045020a58  X3: ffffb4da8e9afa30  X2: ffff0e004502098c  X1: ffffb4da8e9afa30
     X0: 00000124
crash> disas testmod_init
Dump of assembler code for function testmod_init:
   0xffff04d78f4b6000 <+0>:     stp     x29, x30, [sp,#-16]!
   0xffff04d78f4b6004 <+4>:     mov     x29, sp
   0xffff04d78f4b6008 <+8>:     ldr     x0, 0xffff04d78f4b6018
   0xffff04d78f4b600c <+12>:    bl      0xffff04d78f4b6090
   0xffff04d78f4b6010 <+16>:    ldr     x0, 0xffff04d78f4b6020
   0xffff04d78f4b6014 <+20>:    bl      0xffff04d78f4b6080
End of assembler dump.
===>8===
(I see some issue in disassembled code, though.)

> 
> 
> >>> First kernel is booted with mem=2G crashkernel=1G command line option.
> >>> While the system has 64G memory.
> 
> >> Are you saying that "mem=..." doesn't have any effect?
> > What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
> > the memory for second kernel has to be withing the crashkernel size.
> > As per /proc/iomem System RAM the information is correct, but the /proc/meminfo is showing total memory
> > much more than the first kernel had in first place.
> 
> So your second crashkernel has 63G of memory? Unless you provide the same 'mem='
> to the kdump kernel, this is the expected behaviour. The
> DT:/reserved-memory/crash_dump describes the memory not to use.
> 
> On your first boot with 'mem=2G' memblock_mem_limit_remove_map() called from
> arm64_memblock_init() removed the top 62G of memory. Neither the first kernel
> nor kexec-tools know about the top 62G.
> When you run kexec-tools, it describes what it sees in /proc/iomem in the
> DT:/reserved-memory/crash_dump, which is just the remaining 1G of memory.
> 
> When we crash and reboot, the crash kernel discovers all 64G of memory from the
> EFI memory map.
> kexec-tools described the 1G of memory that the first kernel was using in the
> DT:/reserved-memory/crash_dump node, so early_init_fdt_scan_reserved_mem()
> reserves the 1G of memory the first kernel used. This leaves us with 63G of memory.

Thank you very much for elaborating this on behalf of myself!

> This may change with the next version of kdump if it switches back to using
> DT:/chosen/linux,usable-memory-range.

Indeed.
We need to talk to Rob.

Thanks,
-Takahiro AKASHI

> If you need v26 to avoid the top 62G of memory, you need to provide the same
> 'mem=' to the first and second kernel.
>
> 
> >>> 1.2 Live crash dump fails with error
> 
> ... do we expect this to work? I don't think it has anything to do with this
> series...
> 
> 
> Thanks,
> 
> James
> 


From takahiro.akashi at linaro.org  Tue Oct  4 22:48:51 2016
From: takahiro.akashi at linaro.org (AKASHI Takahiro)
Date: Wed, 5 Oct 2016 14:48:51 +0900
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <70ca1b97-8de4-921f-0cef-e02a88691ccd@caviumnetworks.com>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
 <8a57223d-000d-536e-6885-d427ee81508c@caviumnetworks.com>
 <20161003110424.GD14025@linaro.org>
 <1ae717d6-b2aa-105b-4f47-d879882ca5d3@caviumnetworks.com>
 <57F37A73.3030105@arm.com>
 <691230c7-051d-afee-9014-d22963a8f045@caviumnetworks.com>
 <57F38A30.2050200@arm.com>
 <70ca1b97-8de4-921f-0cef-e02a88691ccd@caviumnetworks.com>
Message-ID: <20161005054849.GB19531@linaro.org>

Manish,

On Tue, Oct 04, 2016 at 06:53:28PM +0530, Manish Jaggi wrote:
> 
> On 10/04/2016 04:23 PM, James Morse wrote:
> > Hi Manish,
> > 
> > On 04/10/16 11:05, Manish Jaggi wrote:
> >> On 10/04/2016 03:16 PM, James Morse wrote:
> >>> On 03/10/16 13:41, Manish Jaggi wrote:
> >>>> On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
> >>>>> On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
> >>>>>> First kernel is booted with mem=2G crashkernel=1G command line option.
> >>>>>> While the system has 64G memory.
> >>>
> >>>>> Are you saying that "mem=..." doesn't have any effect?
> >>>> What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
> >>>> the memory for second kernel has to be withing the crashkernel size.
> >>>> As per /proc/iomem System RAM the information is correct, but the /proc/meminfo is showing total memory
> >>>> much more than the first kernel had in first place.
> >>>
> >>> So your second crashkernel has 63G of memory? Unless you provide the same 'mem='
> >>> to the kdump kernel, this is the expected behaviour. The
> >>> DT:/reserved-memory/crash_dump describes the memory not to use.
> >>>
> >>> On your first boot with 'mem=2G' memblock_mem_limit_remove_map() called from
> >>> arm64_memblock_init() removed the top 62G of memory. Neither the first kernel
> >>> nor kexec-tools know about the top 62G.
> >>> When you run kexec-tools, it describes what it sees in /proc/iomem in the
> >>> DT:/reserved-memory/crash_dump, which is just the remaining 1G of memory.
> >>>
> >>> When we crash and reboot, the crash kernel discovers all 64G of memory from the
> >>> EFI memory map.
> > 
> >> So the iomem and meminfo should be same or different for the second kernel?
> >> Also i assumed that crashkernel=1G should restrict the second kernels to 1G.
> > 
> > Not with v26 of this series. What should it do with the 62G of memory that was
> > removed by booting with 'mem=2G'? It isn't part of the crashkernel reserved
> > area, and it isn't part of the vmcore described in elfcorehdr either...
> > 
> > 
> >> This is my understanding from the description. It should not require a second mem= option
> > 
> >>> kexec-tools described the 1G of memory that the first kernel was using in the
> >>> DT:/reserved-memory/crash_dump node, so early_init_fdt_scan_reserved_mem()
> >>> reserves the 1G of memory the first kernel used. This leaves us with 63G of memory.
> >>>
> >>> This may change with the next version of kdump if it switches back to using
> >>> DT:/chosen/linux,usable-memory-range.
> >>> If you need v26 to avoid the top 62G of memory, you need to provide the same
> >>> 'mem=' to the first and second kernel.
> > 
> >> If I provide for second kernel, I dont see any prints after Bye.
> >> Have you tired this anytime?
> > 
> > Yes, on juno-r1 passing 'mem=2G' to both the first and second kernel causes only
> > the first 2G of memory to be used with this pattern:
> > first kernel:		[1G used for linux]	[1G reserved for Crash kernel] 	[6G memory
> > hidden]
> > kdump kernel:	[1G vmcore]			[1G used for linux] 			[6G memory hidden]
> > 
> > 
> Oh, ok!
> I was giving mem=1G to crashkernel to test. with mem=2G it works.

I didn't know that you specified "mem=1G" in our local discussions ...

> >>>>>> 1.2 Live crash dump fails with error
> >>>
> >>> ... do we expect this to work? I don't think it has anything to do with this
> >>> series...
> >>>
> >> Why it should not?
> >> I saved the vmcore file while in second kernel. Since crash without vmcore file didnt run,
> >> Tried with vmcore file and it worked. Its just that if you want to boot a second kernel
> >>  with read only file system without network live crash dump analysis is handy.
> > 
> > Ah, you want to run /usr/bin/crash with the kdump boot of linux. You still need
> > to tell it where to find the memory image: "crash /path/to/vmlinux /proc/vmcore"
> > should do the trick.
> > 
> We should fix the documentation of kdump them.
> Since it is not supported, it should be removed.

Remove what?

And can you please double-check if you still have any problem
on a live system or with a saved core file?
(except for "mem=" stuff)

-Takahiro AKASHI

> > Thanks,
> > 
> > James
> > 


From s.munaut at whatever-company.com  Wed Oct  5 07:06:01 2016
From: s.munaut at whatever-company.com (Sylvain Munaut)
Date: Wed, 5 Oct 2016 16:06:01 +0200
Subject: Patch merging process ?
Message-ID: <CAF6-1L6y2uECc94nJGdPr581Eck6kQMkt1u8rk=jX208SVZA0Q@mail.gmail.com>

Hi,


I sent a series of 3 patch on the mailing list back in August :

http://lists.infradead.org/pipermail/kexec/2016-August/017037.html

They were pretty simple, but I didn't get any feedback (positive or
negative) and I haven't seen them merged either ...

Is there something more expected of me to get these upstream ?


Cheers,

    Sylvain Munaut


From jolsa at redhat.com  Wed Oct  5 09:14:55 2016
From: jolsa at redhat.com (Jiri Olsa)
Date: Wed, 5 Oct 2016 18:14:55 +0200
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
In-Reply-To: <alpine.DEB.2.20.1610041628120.5049@nanos>
References: <1475514432-27682-1-git-send-email-prarit@redhat.com>
 <alpine.DEB.2.20.1610041241160.7712@nanos>
 <57F39C09.10001@redhat.com>
 <alpine.DEB.2.20.1610041628120.5049@nanos>
Message-ID: <20161005161455.GA26029@krava>

On Tue, Oct 04, 2016 at 04:38:16PM +0200, Thomas Gleixner wrote:
> On Tue, 4 Oct 2016, Prarit Bhargava wrote:
> > On 10/04/2016 06:58 AM, Thomas Gleixner wrote:
> > > While it is the right thing to initialize the package map in that case, it
> > > still papers over a robustness issue in the uncore code, which needs to be
> > > fixed first.
> > 
> > I will include a separate patch with an error check for pkg == 0xffff in the
> > uncore code.
> 
> 0xffff? That won't help. The id returned is -1 if the entry is not
> initialized. And aside of that just patching that particular place is not
> helping as the uncore code and also rapl is relying on the package map
> being populated.
> 
> So we need a sanity check in the initialization code which prevents any of
> this being executed.

I still need to test this, but how about something like this?

thanks,
jirka


---
diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
index 28865938aadf..61d087a2f25d 100644
--- a/arch/x86/events/intel/rapl.c
+++ b/arch/x86/events/intel/rapl.c
@@ -598,8 +598,13 @@ static int rapl_cpu_online(unsigned int cpu)
 
 static int rapl_cpu_prepare(unsigned int cpu)
 {
-	struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
+	struct rapl_pmu *pmu;
+	int pkg = topology_logical_package_id(cpu);
+
+	if (WARN_ON(pkg == -1))
+		return -EINVAL;
 
+	pmu = cpu_to_rapl_pmu(cpu);
 	if (pmu)
 		return 0;
 
@@ -613,7 +618,7 @@ static int rapl_cpu_prepare(unsigned int cpu)
 	pmu->timer_interval = ms_to_ktime(rapl_timer_ms);
 	pmu->cpu = -1;
 	rapl_hrtimer_init(pmu);
-	rapl_pmus->pmus[topology_logical_package_id(cpu)] = pmu;
+	rapl_pmus->pmus[pkg] = pmu;
 	return 0;
 }
 
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index 463dc7a5a6c3..3f657fbbf787 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -1352,7 +1352,7 @@ static int __init intel_uncore_init(void)
 {
 	const struct x86_cpu_id *id;
 	struct intel_uncore_init_fun *uncore_init;
-	int pret = 0, cret = 0, ret;
+	int pret = 0, cret = 0, ret, cpu;
 
 	id = x86_match_cpu(intel_uncore_match);
 	if (!id)
@@ -1363,6 +1363,13 @@ static int __init intel_uncore_init(void)
 
 	max_packages = topology_max_packages();
 
+	for_each_present_cpu(cpu) {
+		int pkg = topology_logical_package_id(cpu);
+
+		if (WARN_ON(pkg == -1))
+			return -EINVAL;
+	}
+
 	uncore_init = (struct intel_uncore_init_fun *)id->driver_data;
 	if (uncore_init->pci_init) {
 		pret = uncore_init->pci_init();


From bhe at redhat.com  Wed Oct  5 22:04:43 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 6 Oct 2016 13:04:43 +0800
Subject: Patch merging process ?
In-Reply-To: <CAF6-1L6y2uECc94nJGdPr581Eck6kQMkt1u8rk=jX208SVZA0Q@mail.gmail.com>
References: <CAF6-1L6y2uECc94nJGdPr581Eck6kQMkt1u8rk=jX208SVZA0Q@mail.gmail.com>
Message-ID: <20161006050443.GA17064@x1>

On 10/05/16 at 04:06pm, Sylvain Munaut wrote:
> Hi,
> 
> 
> I sent a series of 3 patch on the mailing list back in August :
> 
> http://lists.infradead.org/pipermail/kexec/2016-August/017037.html
> 
> They were pretty simple, but I didn't get any feedback (positive or
> negative) and I haven't seen them merged either ...
> 
> Is there something more expected of me to get these upstream ?

You can repost. Usually maintainer may be very busy on other issues, you
can ping them one or two weeks later if no feedback.



From bhe at redhat.com  Thu Oct  6 01:46:01 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu,  6 Oct 2016 16:46:01 +0800
Subject: [PATCH] kexec: Export memory sections virtual addresses to vmcoreinfo
Message-ID: <1475743561-23912-1-git-send-email-bhe@redhat.com>

KASLR memory randomization can randomize the base of the physical memory
mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap
(VMEMMAP_START). These need be exported to VMCOREINFO so that user space
utility, mainly makedumpfile can use them to identify the base of each
memory section. Here using VMCOREINFO_NUMBER we can reuse the existing
struct number_table in makedumpfile to import data easily.

Since they are related to x86_64 only, put them into
arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE
together since it's also for x86_64 only.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 arch/x86/kernel/machine_kexec_64.c | 4 ++++
 kernel/kexec_core.c                | 3 ---
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index 5a294e4..e150dd7 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -337,6 +337,10 @@ void arch_crash_save_vmcoreinfo(void)
 #endif
 	vmcoreinfo_append_str("KERNELOFFSET=%lx\n",
 			      kaslr_offset());
+	VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE);
+	VMCOREINFO_NUMBER(PAGE_OFFSET);
+	VMCOREINFO_NUMBER(VMALLOC_START);
+	VMCOREINFO_NUMBER(VMEMMAP_START);
 }
 
 /* arch-dependent functionality related to kexec file-based syscall */
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 5616755..8ad3a29e 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -1467,9 +1467,6 @@ static int __init crash_save_vmcoreinfo_init(void)
 #endif
 	VMCOREINFO_NUMBER(PG_head_mask);
 	VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE);
-#ifdef CONFIG_X86
-	VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE);
-#endif
 #ifdef CONFIG_HUGETLB_PAGE
 	VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR);
 #endif
-- 
2.5.5



From ats-kumagai at wm.jp.nec.com  Thu Oct  6 02:08:03 2016
From: ats-kumagai at wm.jp.nec.com (Atsushi Kumagai)
Date: Thu, 6 Oct 2016 09:08:03 +0000
Subject: [RESEND PATCH 0/8] makedumpfile: Add support to understand
 Power ISA 3.0 based kernel
In-Reply-To: <147503943620.1199.14586683563637783549.stgit@hbathini.in.ibm.com>
References: <147503943620.1199.14586683563637783549.stgit@hbathini.in.ibm.com>
Message-ID: <0910DD04CBD6DE4193FCF86B9C00BE9701E6DDC0@BPXM01GP.gisp.nec.co.jp>

Hello Hari,

>SA 3.0 based kernel
>
>With the introduction of radix MMU in Power ISA 3.0, there are changes
>in kernel page table management accommodating that. This patch series
>makes appropriate changes here to work for such kernels. This series
>enables address translation support for radix MMU and also, fixes a
>few bugs along the way.
>
>Resending the patches:
>* by adding makedumpfile in subject to set this in context
>* adding right mail id of Atsushi Kumagai
>
>---
>
>Hari Bathini (8):
>      ppc64: fix vtop page translation for 4K pages
>      ppc64: Use kernel terminology for each level in 4-level page table
>      ppc64: address changes in kernel v4.5
>      ppc64: address change in _PAGE_PRESNT flag for PowerISA v3.0
>      ppc64: use physical addresses and unfold pud for 64K page size
>      ppc64: support big endian Linux page tables
>      ppc64: use the same masked bit values for 4K and 64K pagesizes
>      ppc64: enable address translation support for radix mmu

I've reviewed them and they look good to me.
I'll merge them into v1.6.1, thanks for your work.

Regards,
Atsushi Kumagai

>
> arch/ppc64.c   |  231 ++++++++++++++++++++++++++++++++++++++++++++++++--------
> makedumpfile.c |   11 +++
> makedumpfile.h |  107 +++++++++++++++++---------
> 3 files changed, 280 insertions(+), 69 deletions(-)


From bhe at redhat.com  Thu Oct  6 02:50:06 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu,  6 Oct 2016 17:50:06 +0800
Subject: [PATCH v2 1/3] makedumpfile: Get info->kernel_version from
 SYMBOL(init_uts_ns) earlier
In-Reply-To: <1475747408-25666-1-git-send-email-bhe@redhat.com>
References: <1475747408-25666-1-git-send-email-bhe@redhat.com>
Message-ID: <1475747408-25666-2-git-send-email-bhe@redhat.com>

The current code assign value to info->kernel_version in check_release,
this is too late and buggy. Because in check_release(), it needs calling
readmem, however earlier get_value_for_old_linux depends on
info->kernel_version to get correct KERNEL_IMAGE_SIZE for MODULES_VADDR
which is used in is_vmalloc_addr_x86_64(). This looks a weird circle.

Since we have exported "OSRELEASE=%s\n" explicitly in kernel, we should
always use it to get kernel version. And this breaks above weird circle.
Otherwise MM randomization will come and make it worse.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 makedumpfile.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index d168dfd..89e1089 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -1139,12 +1139,6 @@ check_release(void)
 		}
 	}
 
-	info->kernel_version = get_kernel_version(info->system_utsname.release);
-	if (info->kernel_version == FALSE) {
-		ERRMSG("Can't get the kernel version.\n");
-		return FALSE;
-	}
-
 	return TRUE;
 }
 
@@ -3832,6 +3826,12 @@ initial(void)
 		debug_info = TRUE;
 	}
 
+	info->kernel_version = get_kernel_version(info->release);
+	if (info->kernel_version == FALSE) {
+		ERRMSG("Can't get the kernel version.\n");
+		return FALSE;
+	}
+
 	if (!get_value_for_old_linux())
 		return FALSE;
 
-- 
2.5.5



From bhe at redhat.com  Thu Oct  6 02:50:05 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu,  6 Oct 2016 17:50:05 +0800
Subject: [PATCH v2 0/3] makedumpfile: Add support of mm randomization
Message-ID: <1475747408-25666-1-git-send-email-bhe@redhat.com>

This is v2 post.

Because of Thomas's kernel patchset, direct mapping, vmalloc and vmemmap
could have random starting address. They need be exported to VMCOREINFO
and let makedumpfile know this so that makedumpfile can identify these
memory areas correctly.

Below is the kernel patchset from Thomas:
x86/mm: memory area address KASLR 
https://lwn.net/Articles/692289/

I have posted a new kernel patchset to export the base of direct mapping,
vmalloc and vmemmap. The subject is:
kexec: Export memory sections virtual addresses to vmcoreinfo

v1->v2:
    According to Atsushi's comment, mainly change patch 3/3.
    - Remove VMALLOC_END_ORIG, VMEMMAP_END_ORIG , VMALLOC_END_2_6_31
      and VMEMMAP_END_2_6_31 since they are not needed anymore.
    - Put those number table member value assignment into
      get_versiondep_info_x86_64.

Baoquan He (3):
  makedumpfile: Get info->kernel_version from SYMBOL(init_uts_ns)
    earlier
  makedumpfile: Move get_versiondep_info calling earlier
  makedumpfile: Add support for MM randomization

 arch/x86_64.c  | 51 ++++++++++++++++++++++++++++++++++-----------------
 makedumpfile.c | 33 ++++++++++++++++-----------------
 makedumpfile.h |  7 +++----
 3 files changed, 53 insertions(+), 38 deletions(-)

-- 
2.5.5



From bhe at redhat.com  Thu Oct  6 02:50:07 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu,  6 Oct 2016 17:50:07 +0800
Subject: [PATCH v2 2/3] makedumpfile: Move get_versiondep_info calling earlier
In-Reply-To: <1475747408-25666-1-git-send-email-bhe@redhat.com>
References: <1475747408-25666-1-git-send-email-bhe@redhat.com>
Message-ID: <1475747408-25666-3-git-send-email-bhe@redhat.com>

Because is_vmalloc_addr_x86_64 need be called very early, e.g in
readmem(). So we have to move get_versiondep_info calling earlier
to let PAGE_OFFSET/VMALLOC_START/VMEMMAP_START get value before
use them.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 makedumpfile.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/makedumpfile.c b/makedumpfile.c
index 89e1089..e132550 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -3835,6 +3835,9 @@ initial(void)
 	if (!get_value_for_old_linux())
 		return FALSE;
 
+	if (!get_versiondep_info())
+		return FALSE;
+
 	if (info->flag_mem_usage && !get_kcore_dump_loads())
 		return FALSE;
 
@@ -3986,9 +3989,6 @@ out:
 		if (!check_release())
 			return FALSE;
 
-		if (!get_versiondep_info())
-			return FALSE;
-
 		/*
 		 * NOTE: This must be done before refering to
 		 * VMALLOC'ed memory. The first 640kB contains data
-- 
2.5.5



From bhe at redhat.com  Thu Oct  6 02:50:08 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu,  6 Oct 2016 17:50:08 +0800
Subject: [PATCH v2 3/3] makedumpfile: Add support for MM randomization
In-Reply-To: <1475747408-25666-1-git-send-email-bhe@redhat.com>
References: <1475747408-25666-1-git-send-email-bhe@redhat.com>
Message-ID: <1475747408-25666-4-git-send-email-bhe@redhat.com>

In kernel patchset "x86/mm: memory area address KASLR", PAGE_OFFSET,
VMALLOC_START and VMEMMAP_START are all randomized. Please check below
link:
	https://lwn.net/Articles/692289/

And these need be exported into vmcoreinfo and tell makedumpfile. In
this patch get and handle them to support MM randomization.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 arch/x86_64.c  | 51 ++++++++++++++++++++++++++++++++++-----------------
 makedumpfile.c | 15 +++++++--------
 makedumpfile.h |  7 +++----
 3 files changed, 44 insertions(+), 29 deletions(-)

diff --git a/arch/x86_64.c b/arch/x86_64.c
index ddf7be6..1fd193f 100644
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -146,8 +146,9 @@ get_machdep_info_x86_64(void)
 	return TRUE;
 }
 
-int
-get_versiondep_info_x86_64(void)
+#define VMALLOC_SIZE            (0x200000000000)
+#define VMEMMAP_SIZE            (0x10000000000)
+int get_versiondep_info_x86_64(void)
 {
 	/*
 	 * On linux-2.6.26, MAX_PHYSMEM_BITS is changed to 44 from 40.
@@ -159,22 +160,38 @@ get_versiondep_info_x86_64(void)
 	else
 		info->max_physmem_bits  = _MAX_PHYSMEM_BITS_2_6_31;
 
-	if (info->kernel_version < KERNEL_VERSION(2, 6, 27))
-		info->page_offset = __PAGE_OFFSET_ORIG;
-	else
-		info->page_offset = __PAGE_OFFSET_2_6_27;
-
-	if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
-		info->vmalloc_start = VMALLOC_START_ORIG;
-		info->vmalloc_end   = VMALLOC_END_ORIG;
-		info->vmemmap_start = VMEMMAP_START_ORIG;
-		info->vmemmap_end   = VMEMMAP_END_ORIG;
-	} else {
-		info->vmalloc_start = VMALLOC_START_2_6_31;
-		info->vmalloc_end   = VMALLOC_END_2_6_31;
-		info->vmemmap_start = VMEMMAP_START_2_6_31;
-		info->vmemmap_end   = VMEMMAP_END_2_6_31;
+	if (NUMBER(KERNEL_IMAGE_SIZE) == NOT_FOUND_NUMBER) {
+		if (info->kernel_version < KERNEL_VERSION(2, 6, 26))
+			NUMBER(KERNEL_IMAGE_SIZE) = KERNEL_IMAGE_SIZE_ORIG;
+		else
+			NUMBER(KERNEL_IMAGE_SIZE) = KERNEL_IMAGE_SIZE_2_6_26;
+	}
+	if (NUMBER(page_offset) == NOT_FOUND_NUMBER) {
+		if (info->kernel_version < KERNEL_VERSION(2, 6, 27))
+			NUMBER(page_offset) = __PAGE_OFFSET_ORIG;
+		else
+			NUMBER(page_offset) = __PAGE_OFFSET_2_6_27;
 	}
+	if (NUMBER(vmalloc_start) == NOT_FOUND_NUMBER) {
+		if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
+			NUMBER(vmalloc_start) = VMALLOC_START_ORIG;
+		} else {
+			NUMBER(vmalloc_start) = VMALLOC_START_2_6_31;
+		}
+	}
+	if (NUMBER(vmemmap_start) == NOT_FOUND_NUMBER) {
+		if (info->kernel_version < KERNEL_VERSION(2, 6, 31))
+			NUMBER(vmemmap_start) = VMEMMAP_START_ORIG;
+		else
+			NUMBER(vmemmap_start) = VMEMMAP_START_2_6_31;
+	}
+
+	info->page_offset = NUMBER(page_offset);
+
+	info->vmalloc_start = NUMBER(vmalloc_start);
+	info->vmalloc_end   = info->vmalloc_start + VMALLOC_SIZE - 1;
+	info->vmemmap_start = NUMBER(vmemmap_start);
+	info->vmemmap_end   = info->vmemmap_start + VMEMMAP_SIZE - 1;
 
 	return TRUE;
 }
diff --git a/makedumpfile.c b/makedumpfile.c
index e132550..bf990f1 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -1985,14 +1985,7 @@ get_value_for_old_linux(void)
 			NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE) =
 			PAGE_BUDDY_MAPCOUNT_VALUE_v2_6_39_to_latest_version;
 	}
-#ifdef __x86_64__
-	if (NUMBER(KERNEL_IMAGE_SIZE) == NOT_FOUND_NUMBER) {
-		if (info->kernel_version < KERNEL_VERSION(2, 6, 26))
-			NUMBER(KERNEL_IMAGE_SIZE) = KERNEL_IMAGE_SIZE_ORIG;
-		else
-			NUMBER(KERNEL_IMAGE_SIZE) = KERNEL_IMAGE_SIZE_2_6_26;
-	}
-#endif
+
 	if (SIZE(pageflags) == NOT_FOUND_STRUCTURE) {
 		if (info->kernel_version >= KERNEL_VERSION(2, 6, 27))
 			SIZE(pageflags) =
@@ -2249,6 +2242,9 @@ write_vmcoreinfo_data(void)
 
 	WRITE_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE);
 	WRITE_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE);
+	WRITE_NUMBER("PAGE_OFFSET", page_offset);
+	WRITE_NUMBER("VMALLOC_START", vmalloc_start);
+	WRITE_NUMBER("VMEMMAP_START", vmemmap_start);
 
 	WRITE_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
 
@@ -2595,6 +2591,9 @@ read_vmcoreinfo(void)
 
 	READ_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE);
 	READ_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE);
+	READ_NUMBER("PAGE_OFFSET", page_offset);
+	READ_NUMBER("VMALLOC_START", vmalloc_start);
+	READ_NUMBER("VMEMMAP_START", vmemmap_start);
 
 	READ_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
 
diff --git a/makedumpfile.h b/makedumpfile.h
index 1814139..17f71a3 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -564,13 +564,9 @@ int get_va_bits_arm64(void);
 
 #define VMALLOC_START_ORIG	(0xffffc20000000000) /* 2.6.30, or former */
 #define VMALLOC_START_2_6_31	(0xffffc90000000000) /* 2.6.31, or later  */
-#define VMALLOC_END_ORIG	(0xffffe1ffffffffff) /* 2.6.30, or former */
-#define VMALLOC_END_2_6_31	(0xffffe8ffffffffff) /* 2.6.31, or later  */
 
 #define VMEMMAP_START_ORIG	(0xffffe20000000000) /* 2.6.30, or former */
 #define VMEMMAP_START_2_6_31	(0xffffea0000000000) /* 2.6.31, or later  */
-#define VMEMMAP_END_ORIG	(0xffffe2ffffffffff) /* 2.6.30, or former */
-#define VMEMMAP_END_2_6_31	(0xffffeaffffffffff) /* 2.6.31, or later  */
 
 #define __START_KERNEL_map	(0xffffffff80000000)
 #define KERNEL_IMAGE_SIZE_ORIG		(0x0000000008000000) /* 2.6.25, or former */
@@ -1685,6 +1681,9 @@ struct number_table {
 
 	long	PAGE_BUDDY_MAPCOUNT_VALUE;
 	long	KERNEL_IMAGE_SIZE;
+	long	page_offset;
+	long	vmalloc_start;
+	long	vmemmap_start;
 	long	SECTION_SIZE_BITS;
 	long	MAX_PHYSMEM_BITS;
 	long    HUGETLB_PAGE_DTOR;
-- 
2.5.5



From bhe at redhat.com  Thu Oct  6 03:23:53 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 6 Oct 2016 18:23:53 +0800
Subject: [PATCH v2 0/3] makedumpfile: Add support of mm randomization
In-Reply-To: <1475747408-25666-1-git-send-email-bhe@redhat.com>
References: <1475747408-25666-1-git-send-email-bhe@redhat.com>
Message-ID: <20161006102353.GA17662@x1>

Oops, I just sent to Atsushi's old mail. Sorry about this!

On 10/06/16 at 05:50pm, Baoquan He wrote:
> This is v2 post.
> 
> Because of Thomas's kernel patchset, direct mapping, vmalloc and vmemmap
> could have random starting address. They need be exported to VMCOREINFO
> and let makedumpfile know this so that makedumpfile can identify these
> memory areas correctly.
> 
> Below is the kernel patchset from Thomas:
> x86/mm: memory area address KASLR 
> https://lwn.net/Articles/692289/
> 
> I have posted a new kernel patchset to export the base of direct mapping,
> vmalloc and vmemmap. The subject is:
> kexec: Export memory sections virtual addresses to vmcoreinfo
> 
> v1->v2:
>     According to Atsushi's comment, mainly change patch 3/3.
>     - Remove VMALLOC_END_ORIG, VMEMMAP_END_ORIG , VMALLOC_END_2_6_31
>       and VMEMMAP_END_2_6_31 since they are not needed anymore.
>     - Put those number table member value assignment into
>       get_versiondep_info_x86_64.
> 
> Baoquan He (3):
>   makedumpfile: Get info->kernel_version from SYMBOL(init_uts_ns)
>     earlier
>   makedumpfile: Move get_versiondep_info calling earlier
>   makedumpfile: Add support for MM randomization
> 
>  arch/x86_64.c  | 51 ++++++++++++++++++++++++++++++++++-----------------
>  makedumpfile.c | 33 ++++++++++++++++-----------------
>  makedumpfile.h |  7 +++----
>  3 files changed, 53 insertions(+), 38 deletions(-)
> 
> -- 
> 2.5.5
> 


From matthias.bgg at gmail.com  Thu Oct  6 06:28:12 2016
From: matthias.bgg at gmail.com (Matthias Brugger)
Date: Thu, 6 Oct 2016 15:28:12 +0200
Subject: [PATCH v3 2/8] kexec: generalize and rename get_kernel_stext_sym()
In-Reply-To: <20160907043401.6403-3-takahiro.akashi@linaro.org>
References: <20160907043401.6403-1-takahiro.akashi@linaro.org>
 <20160907043401.6403-3-takahiro.akashi@linaro.org>
Message-ID: <b88cbd6b-923d-d0c9-ce23-b9ef99aca256@gmail.com>

On 09/07/2016 06:33 AM, AKASHI Takahiro wrote:
> From: Pratyush Anand <panand at redhat.com>
>
> get_kernel_stext_sym() has been defined for both arm and i386. Other
> architecture might need some other kernel symbol address. Therefore rewrite
> this function as generic function to get any kernel symbol address.
>
> More over, kallsyms is not arch specific representation, therefore have
> common function for all arches.
>
> Signed-off-by: Pratyush Anand <panand at redhat.com>
> [created symbols.c]
> Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> ---
>  kexec/Makefile                  |  1 +
>  kexec/arch/arm/crashdump-arm.c  | 40 +---------------------------------------
>  kexec/arch/i386/crashdump-x86.c | 32 +-------------------------------
>  kexec/kexec.h                   |  2 ++
>  kexec/symbols.c                 | 41 +++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 46 insertions(+), 70 deletions(-)
>  create mode 100644 kexec/symbols.c
>
> diff --git a/kexec/Makefile b/kexec/Makefile
> index 39f365f..2b4fb3d 100644
> --- a/kexec/Makefile
> +++ b/kexec/Makefile
> @@ -26,6 +26,7 @@ KEXEC_SRCS_base += kexec/kernel_version.c
>  KEXEC_SRCS_base += kexec/lzma.c
>  KEXEC_SRCS_base += kexec/zlib.c
>  KEXEC_SRCS_base += kexec/kexec-xen.c
> +KEXEC_SRCS_base += kexec/symbols.c
>
>  KEXEC_GENERATED_SRCS += $(PURGATORY_HEX_C)
>
> diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
> index 4a89b5e..2bc898b 100644
> --- a/kexec/arch/arm/crashdump-arm.c
> +++ b/kexec/arch/arm/crashdump-arm.c
> @@ -73,48 +73,10 @@ static struct crash_elf_info elf_info = {
>
>  extern unsigned long long user_page_offset;
>
> -/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */
> -static unsigned long long get_kernel_stext_sym(void)
> -{
> -	const char *kallsyms = "/proc/kallsyms";
> -	const char *stext = "_stext";
> -	char sym[128];
> -	char line[128];
> -	FILE *fp;
> -	unsigned long long vaddr = 0;
> -	char type;
> -
> -	fp = fopen(kallsyms, "r");
> -	if (!fp) {
> -		fprintf(stderr, "Cannot open %s\n", kallsyms);
> -		return 0;
> -	}
> -
> -	while(fgets(line, sizeof(line), fp) != NULL) {
> -		unsigned long long addr;
> -
> -		if (sscanf(line, "%Lx %c %s", &addr, &type, sym) != 3)
> -			continue;
> -
> -		if (strcmp(sym, stext) == 0) {
> -			dbgprintf("kernel symbol %s vaddr = %#llx\n", stext, addr);
> -			vaddr = addr;
> -			break;
> -		}
> -	}
> -
> -	fclose(fp);
> -
> -	if (vaddr == 0)
> -		fprintf(stderr, "Cannot get kernel %s symbol address\n", stext);
> -
> -	return vaddr;
> -}
> -
>  static int get_kernel_page_offset(struct kexec_info *info,
>  		struct crash_elf_info *elf_info)
>  {
> -	unsigned long long stext_sym_addr = get_kernel_stext_sym();
> +	unsigned long long stext_sym_addr = get_kernel_sym("stext");
>  	if (stext_sym_addr == 0) {
>  		if (user_page_offset != (-1ULL)) {
>  			elf_info->page_offset = user_page_offset;
> diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
> index bbc0f35..664eb3b 100644
> --- a/kexec/arch/i386/crashdump-x86.c
> +++ b/kexec/arch/i386/crashdump-x86.c
> @@ -102,36 +102,6 @@ static int get_kernel_paddr(struct kexec_info *UNUSED(info),
>  	return -1;
>  }
>
> -/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */
> -static unsigned long long get_kernel_stext_sym(void)
> -{
> -	const char *kallsyms = "/proc/kallsyms";
> -	const char *stext = "_stext";
> -	char sym[128];
> -	char line[128];
> -	FILE *fp;
> -	unsigned long long vaddr;
> -	char type;
> -
> -	fp = fopen(kallsyms, "r");
> -	if (!fp) {
> -		fprintf(stderr, "Cannot open %s\n", kallsyms);
> -		return 0;
> -	}
> -
> -	while(fgets(line, sizeof(line), fp) != NULL) {
> -		if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
> -			continue;
> -		if (strcmp(sym, stext) == 0) {
> -			dbgprintf("kernel symbol %s vaddr = %16llx\n", stext, vaddr);
> -			return vaddr;
> -		}
> -	}
> -
> -	fprintf(stderr, "Cannot get kernel %s symbol address\n", stext);
> -	return 0;
> -}
> -
>  /* Retrieve info regarding virtual address kernel has been compiled for and
>   * size of the kernel from /proc/kcore. Current /proc/kcore parsing from
>   * from kexec-tools fails because of malformed elf notes. A kernel patch has
> @@ -182,7 +152,7 @@ static int get_kernel_vaddr_and_size(struct kexec_info *UNUSED(info),
>
>  	/* Traverse through the Elf headers and find the region where
>  	 * _stext symbol is located in. That's where kernel is mapped */
> -	stext_sym = get_kernel_stext_sym();
> +	stext_sym = get_kernel_sym("stext");


I think this should be get_kernel_sym("_stext");

Apart from that as Simon already mentioned, due to commit
9f62cbd ("kexec/arch/i386: Add support for KASLR memory randomization")
this patch does not apply cleanly.

Regards,
Matthias

>  	for(phdr = ehdr.e_phdr; stext_sym && phdr != end_phdr; phdr++) {
>  		if (phdr->p_type == PT_LOAD) {
>  			unsigned long long saddr = phdr->p_vaddr;
> diff --git a/kexec/kexec.h b/kexec/kexec.h
> index 9194f1c..b4fafad 100644
> --- a/kexec/kexec.h
> +++ b/kexec/kexec.h
> @@ -312,4 +312,6 @@ int xen_kexec_load(struct kexec_info *info);
>  int xen_kexec_unload(uint64_t kexec_flags);
>  void xen_kexec_exec(void);
>
> +extern unsigned long long get_kernel_sym(const char *text);
> +
>  #endif /* KEXEC_H */
> diff --git a/kexec/symbols.c b/kexec/symbols.c
> new file mode 100644
> index 0000000..ea6e327
> --- /dev/null
> +++ b/kexec/symbols.c
> @@ -0,0 +1,41 @@
> +#include <stdio.h>
> +#include <string.h>
> +#include "kexec.h"
> +
> +/* Retrieve kernel symbol virtual address from /proc/kallsyms */
> +unsigned long long get_kernel_sym(const char *text)
> +{
> +	const char *kallsyms = "/proc/kallsyms";
> +	char sym[128];
> +	char line[128];
> +	FILE *fp;
> +	unsigned long long vaddr = 0;
> +	char type;
> +
> +	fp = fopen(kallsyms, "r");
> +	if (!fp) {
> +		fprintf(stderr, "Cannot open %s\n", kallsyms);
> +		return 0;
> +	}
> +
> +	while (fgets(line, sizeof(line), fp) != NULL) {
> +		unsigned long long addr;
> +
> +		if (sscanf(line, "%Lx %c %s", &addr, &type, sym) != 3)
> +			continue;
> +
> +		if (strcmp(sym, text) == 0) {
> +			dbgprintf("kernel symbol %s vaddr = %#llx\n",
> +								text, addr);
> +			vaddr = addr;
> +			break;
> +		}
> +	}
> +
> +	fclose(fp);
> +
> +	if (vaddr == 0)
> +		fprintf(stderr, "Cannot get kernel %s symbol address\n", text);
> +
> +	return vaddr;
> +}
>




From prarit at redhat.com  Thu Oct  6 08:25:43 2016
From: prarit at redhat.com (Prarit Bhargava)
Date: Thu, 06 Oct 2016 11:25:43 -0400
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
In-Reply-To: <20161005161455.GA26029@krava>
References: <1475514432-27682-1-git-send-email-prarit@redhat.com>
 <alpine.DEB.2.20.1610041241160.7712@nanos> <57F39C09.10001@redhat.com>
 <alpine.DEB.2.20.1610041628120.5049@nanos> <20161005161455.GA26029@krava>
Message-ID: <57F66CF7.7040204@redhat.com>



On 10/05/2016 12:14 PM, Jiri Olsa wrote:
> On Tue, Oct 04, 2016 at 04:38:16PM +0200, Thomas Gleixner wrote:
>> On Tue, 4 Oct 2016, Prarit Bhargava wrote:
>>> On 10/04/2016 06:58 AM, Thomas Gleixner wrote:
>>>> While it is the right thing to initialize the package map in that case, it
>>>> still papers over a robustness issue in the uncore code, which needs to be
>>>> fixed first.
>>>
>>> I will include a separate patch with an error check for pkg == 0xffff in the
>>> uncore code.
>>
>> 0xffff? That won't help. The id returned is -1 if the entry is not
>> initialized. And aside of that just patching that particular place is not
>> helping as the uncore code and also rapl is relying on the package map
>> being populated.
>>
>> So we need a sanity check in the initialization code which prevents any of
>> this being executed.
> 
> I still need to test this, but how about something like this?
> 
> thanks,
> jirka
> 
> 
> ---
> diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
> index 28865938aadf..61d087a2f25d 100644
> --- a/arch/x86/events/intel/rapl.c
> +++ b/arch/x86/events/intel/rapl.c
> @@ -598,8 +598,13 @@ static int rapl_cpu_online(unsigned int cpu)
>  
>  static int rapl_cpu_prepare(unsigned int cpu)
>  {
> -	struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
> +	struct rapl_pmu *pmu;
> +	int pkg = topology_logical_package_id(cpu);
> +
> +	if (WARN_ON(pkg == -1))
> +		return -EINVAL;
>  
> +	pmu = cpu_to_rapl_pmu(cpu);
>  	if (pmu)
>  		return 0;

I thought about doing this but it seems like every time some driver uses
topology_logical_package_id() the driver would have to replicate the error
checking code.

P.


From ebiederm at xmission.com  Thu Oct  6 13:07:53 2016
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Thu, 06 Oct 2016 15:07:53 -0500
Subject: [PATCH] kexec: Export memory sections virtual addresses to
 vmcoreinfo
In-Reply-To: <1475743561-23912-1-git-send-email-bhe@redhat.com> (Baoquan He's
 message of "Thu, 6 Oct 2016 16:46:01 +0800")
References: <1475743561-23912-1-git-send-email-bhe@redhat.com>
Message-ID: <877f9lckbq.fsf@x220.int.ebiederm.org>

Baoquan He <bhe at redhat.com> writes:

> KASLR memory randomization can randomize the base of the physical memory
> mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap
> (VMEMMAP_START). These need be exported to VMCOREINFO so that user space
> utility, mainly makedumpfile can use them to identify the base of each
> memory section. Here using VMCOREINFO_NUMBER we can reuse the existing
> struct number_table in makedumpfile to import data easily.
>
> Since they are related to x86_64 only, put them into
> arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE
> together since it's also for x86_64 only.

*Scratches my head*  I would have thought this information would have
better fit in the ELF header.  Where it actually has a field for virtual
address.  It also has a field for physical address, and a third field
for offset in the file (which is where the kdump finds these things in
memory aftewards).

Why do we need need more magic vmcoreinfo to handle this?

Eric

 
>
> Signed-off-by: Baoquan He <bhe at redhat.com>
> ---
>  arch/x86/kernel/machine_kexec_64.c | 4 ++++
>  kernel/kexec_core.c                | 3 ---
>  2 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
> index 5a294e4..e150dd7 100644
> --- a/arch/x86/kernel/machine_kexec_64.c
> +++ b/arch/x86/kernel/machine_kexec_64.c
> @@ -337,6 +337,10 @@ void arch_crash_save_vmcoreinfo(void)
>  #endif
>  	vmcoreinfo_append_str("KERNELOFFSET=%lx\n",
>  			      kaslr_offset());
> +	VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE);
> +	VMCOREINFO_NUMBER(PAGE_OFFSET);
> +	VMCOREINFO_NUMBER(VMALLOC_START);
> +	VMCOREINFO_NUMBER(VMEMMAP_START);
>  }
>  
>  /* arch-dependent functionality related to kexec file-based syscall */
> diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
> index 5616755..8ad3a29e 100644
> --- a/kernel/kexec_core.c
> +++ b/kernel/kexec_core.c
> @@ -1467,9 +1467,6 @@ static int __init crash_save_vmcoreinfo_init(void)
>  #endif
>  	VMCOREINFO_NUMBER(PG_head_mask);
>  	VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE);
> -#ifdef CONFIG_X86
> -	VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE);
> -#endif
>  #ifdef CONFIG_HUGETLB_PAGE
>  	VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR);
>  #endif


From horms at verge.net.au  Thu Oct  6 19:52:21 2016
From: horms at verge.net.au (Simon Horman)
Date: Fri, 7 Oct 2016 11:52:21 +0900
Subject: Patch merging process ?
In-Reply-To: <20161006050443.GA17064@x1>
References: <CAF6-1L6y2uECc94nJGdPr581Eck6kQMkt1u8rk=jX208SVZA0Q@mail.gmail.com>
 <20161006050443.GA17064@x1>
Message-ID: <20161007025221.GE13721@verge.net.au>

On Thu, Oct 06, 2016 at 01:04:43PM +0800, Baoquan He wrote:
> On 10/05/16 at 04:06pm, Sylvain Munaut wrote:
> > Hi,
> > 
> > 
> > I sent a series of 3 patch on the mailing list back in August :
> > 
> > http://lists.infradead.org/pipermail/kexec/2016-August/017037.html
> > 
> > They were pretty simple, but I didn't get any feedback (positive or
> > negative) and I haven't seen them merged either ...
> > 
> > Is there something more expected of me to get these upstream ?
> 
> You can repost. Usually maintainer may be very busy on other issues, you
> can ping them one or two weeks later if no feedback.

I apologise that I have been unusually busy over the past months
and I seem to have missed the patches you mention.

Please re-post any patches for kexec-tools and I will look over them.


From horms at verge.net.au  Thu Oct  6 19:55:33 2016
From: horms at verge.net.au (Simon Horman)
Date: Fri, 7 Oct 2016 11:55:33 +0900
Subject: [PATCH 1/3] kexec elf: Sanity check on the note header before
 accessing it
In-Reply-To: <1472215576-7466-1-git-send-email-s.munaut@whatever-company.com>
References: <1472215576-7466-1-git-send-email-s.munaut@whatever-company.com>
Message-ID: <20161007025533.GF13721@verge.net.au>

On Fri, Aug 26, 2016 at 12:46:14PM +0000, Sylvain Munaut wrote:
> The name[hdr.n_namesz -1] check below can segfault if the header
> is garbage. So we check the computed header side fits within
> the expected area before going further.
> 
> Signed-off-by: Sylvain Munaut <s.munaut at whatever-company.com>

Thanks, I have applied this and the other two patches in this series.


From horms at verge.net.au  Thu Oct  6 19:56:59 2016
From: horms at verge.net.au (Simon Horman)
Date: Fri, 7 Oct 2016 11:56:59 +0900
Subject: [PATCH v3] kexec/fs2dt: Check for NULL pointer in
 dt_copy_old_root_param()
In-Reply-To: <1475545025-31977-1-git-send-email-maddy@linux.vnet.ibm.com>
References: <1475545025-31977-1-git-send-email-maddy@linux.vnet.ibm.com>
Message-ID: <20161007025659.GG13721@verge.net.au>

On Tue, Oct 04, 2016 at 07:07:05AM +0530, Madhavan Srinivasan wrote:
> In dt_copy_old_root_param(), FILE * returned
> from fopen is not checked for NULL pointer
> before passinig to fclose(). This could trigger
> a segfault. Patch to fix the same.
> 
> Signed-off-by: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>

Thanks, applied.


From dyoung at redhat.com  Thu Oct  6 21:06:57 2016
From: dyoung at redhat.com (Dave Young)
Date: Fri, 7 Oct 2016 12:06:57 +0800
Subject: [PATCH v3] kexec/fs2dt: Check for NULL pointer in
 dt_copy_old_root_param()
In-Reply-To: <1475545025-31977-1-git-send-email-maddy@linux.vnet.ibm.com>
References: <1475545025-31977-1-git-send-email-maddy@linux.vnet.ibm.com>
Message-ID: <20161007040657.GB16400@dhcp-128-65.nay.redhat.com>

On 10/04/16 at 07:07am, Madhavan Srinivasan wrote:
> In dt_copy_old_root_param(), FILE * returned
> from fopen is not checked for NULL pointer
> before passinig to fclose(). This could trigger
> a segfault. Patch to fix the same.
> 
> Signed-off-by: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>
> ---
> Changelog v2
> -Removed redundant check fp
> 
> Changelog v1:
> - Moved the check right after fopen
>  
>  kexec/fs2dt.c | 26 ++++++++++++++------------
>  1 file changed, 14 insertions(+), 12 deletions(-)
> 
> diff --git a/kexec/fs2dt.c b/kexec/fs2dt.c
> index 6ed2399759cf..79aa0f320a5a 100644
> --- a/kexec/fs2dt.c
> +++ b/kexec/fs2dt.c
> @@ -524,19 +524,21 @@ static void dt_copy_old_root_param(void)
>  	strcpy(filename, pathname);
>  	strcat(filename, "bootargs");
>  	fp = fopen(filename, "r");
> -	if (fp) {
> -		if (getline(&last_cmdline, &len, fp) == -1)
> -			die("unable to read %s\n", filename);
> -
> -		p = strstr(last_cmdline, "root=");
> -		if (p) {
> -			old_param = strtok(p, " ");
> -			len = strlen(local_cmdline);
> -			if (len != 0)
> -				strcat(local_cmdline, " ");
> -			strcat(local_cmdline, old_param);
> -		}
> +	if (!fp)
> +		return;
> +
> +	if (getline(&last_cmdline, &len, fp) == -1)
> +		die("unable to read %s\n", filename);
> +
> +	p = strstr(last_cmdline, "root=");
> +	if (p) {
> +		old_param = strtok(p, " ");
> +		len = strlen(local_cmdline);
> +		if (len != 0)
> +			strcat(local_cmdline, " ");
> +		strcat(local_cmdline, old_param);
>  	}
> +
>  	if (last_cmdline)
>  		free(last_cmdline);
>  
> -- 
> 2.7.4
> 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec

Reviewed-by: Dave Young <dyoung at redhat.com>

Thanks
Dave


From dyoung at redhat.com  Thu Oct  6 21:18:37 2016
From: dyoung at redhat.com (Dave Young)
Date: Fri, 7 Oct 2016 12:18:37 +0800
Subject: [PATCH v3 2/8] kexec: generalize and rename get_kernel_stext_sym()
In-Reply-To: <b88cbd6b-923d-d0c9-ce23-b9ef99aca256@gmail.com>
References: <20160907043401.6403-1-takahiro.akashi@linaro.org>
 <20160907043401.6403-3-takahiro.akashi@linaro.org>
 <b88cbd6b-923d-d0c9-ce23-b9ef99aca256@gmail.com>
Message-ID: <20161007041837.GC16400@dhcp-128-65.nay.redhat.com>

> >  	/* Traverse through the Elf headers and find the region where
> >  	 * _stext symbol is located in. That's where kernel is mapped */
> > -	stext_sym = get_kernel_stext_sym();
> > +	stext_sym = get_kernel_sym("stext");
> 
> 
> I think this should be get_kernel_sym("_stext");
> 
> Apart from that as Simon already mentioned, due to commit
> 9f62cbd ("kexec/arch/i386: Add support for KASLR memory randomization")
> this patch does not apply cleanly.

Pratyush, I had a cleanup patch below, but I did not get time to test it
so it is not ready to send out.

The basic thought is to move the page_offset_base code to
get_kernel_page_offset(), there is also another issue is for old kernel
or kernel without kaslr built-in there will be an unnecessary error
message but I have not get any idea how to fix it.

Would you like to take below cleanup patch along with your next version?
It is also fine to leave it as a future improvement to me.

Thanks
Dave

---
 kexec/arch/i386/crashdump-x86.c |  158 ++++++++++++++++++++--------------------
 1 file changed, 82 insertions(+), 76 deletions(-)

--- kexec-tools.orig/kexec/arch/i386/crashdump-x86.c
+++ kexec-tools/kexec/arch/i386/crashdump-x86.c
@@ -54,10 +54,59 @@
 
 extern struct arch_options_t arch_options;
 
+/* Retrieve kernel symbol virtual address from /proc/kallsyms */
+static unsigned long long get_kernel_sym(const char *symbol)
+{
+	const char *kallsyms = "/proc/kallsyms";
+	char sym[128];
+	char line[128];
+	FILE *fp;
+	unsigned long long vaddr;
+	char type;
+
+	fp = fopen(kallsyms, "r");
+	if (!fp) {
+		fprintf(stderr, "Cannot open %s\n", kallsyms);
+		return 0;
+	}
+
+	while(fgets(line, sizeof(line), fp) != NULL) {
+		if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
+			continue;
+		if (strcmp(sym, symbol) == 0) {
+			dbgprintf("kernel symbol %s vaddr = %16llx\n", symbol, vaddr);
+			return vaddr;
+		}
+	}
+
+	fprintf(stderr, "Cannot get kernel %s symbol address\n", symbol);
+
+	return 0;
+}
+
 static int get_kernel_page_offset(struct kexec_info *UNUSED(info),
-				  struct crash_elf_info *elf_info)
+				  struct crash_elf_info *elf_info,
+				  struct mem_ehdr *ehdr)
 {
 	int kv;
+	struct mem_phdr *phdr, *end_phdr;
+	const unsigned long long pud_mask = ~((1 << 30) - 1);
+	unsigned long long vaddr, lowest_vaddr = 0;
+
+	end_phdr = &ehdr->e_phdr[ehdr->e_phnum];
+	/* Search for the real PAGE_OFFSET when KASLR memory randomization
+	 * is enabled */
+	if (get_kernel_sym("page_offset_base") != 0) {
+		for(phdr = ehdr->e_phdr; phdr != end_phdr; phdr++) {
+			if (phdr->p_type == PT_LOAD) {
+				vaddr = phdr->p_vaddr & pud_mask;
+				if (lowest_vaddr == 0 || lowest_vaddr > vaddr)
+					lowest_vaddr = vaddr;
+			}
+		}
+		if (lowest_vaddr != 0)
+			elf_info->page_offset = lowest_vaddr;
+	}
 
 	if (elf_info->machine == EM_X86_64) {
 		kv = kernel_version();
@@ -102,35 +151,6 @@ static int get_kernel_paddr(struct kexec
 	return -1;
 }
 
-/* Retrieve kernel symbol virtual address from /proc/kallsyms */
-static unsigned long long get_kernel_sym(const char *symbol)
-{
-	const char *kallsyms = "/proc/kallsyms";
-	char sym[128];
-	char line[128];
-	FILE *fp;
-	unsigned long long vaddr;
-	char type;
-
-	fp = fopen(kallsyms, "r");
-	if (!fp) {
-		fprintf(stderr, "Cannot open %s\n", kallsyms);
-		return 0;
-	}
-
-	while(fgets(line, sizeof(line), fp) != NULL) {
-		if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
-			continue;
-		if (strcmp(sym, symbol) == 0) {
-			dbgprintf("kernel symbol %s vaddr = %16llx\n", symbol, vaddr);
-			return vaddr;
-		}
-	}
-
-	fprintf(stderr, "Cannot get kernel %s symbol address\n", symbol);
-	return 0;
-}
-
 /* Retrieve info regarding virtual address kernel has been compiled for and
  * size of the kernel from /proc/kcore. Current /proc/kcore parsing from
  * from kexec-tools fails because of malformed elf notes. A kernel patch has
@@ -139,19 +159,12 @@ static unsigned long long get_kernel_sym
  * we should get rid of backward compatible code. */
 
 static int get_kernel_vaddr_and_size(struct kexec_info *UNUSED(info),
-				     struct crash_elf_info *elf_info)
+				     struct crash_elf_info *elf_info,
+				     struct mem_ehdr *ehdr)
 {
-	int result;
-	const char kcore[] = "/proc/kcore";
-	char *buf;
-	struct mem_ehdr ehdr;
 	struct mem_phdr *phdr, *end_phdr;
 	int align;
-	off_t size;
-	uint32_t elf_flags = 0;
 	uint64_t stext_sym;
-	const unsigned long long pud_mask = ~((1 << 30) - 1);
-	unsigned long long vaddr, lowest_vaddr = 0;
 
 	if (elf_info->machine != EM_X86_64)
 		return 0;
@@ -160,45 +173,13 @@ static int get_kernel_vaddr_and_size(str
 		return 0;
 
 	align = getpagesize();
-	buf = slurp_file_len(kcore, KCORE_ELF_HEADERS_SIZE, &size);
-	if (!buf) {
-		fprintf(stderr, "Cannot read %s: %s\n", kcore, strerror(errno));
-		return -1;
-	}
 
-	/* Don't perform checks to make sure stated phdrs and shdrs are
-	 * actually present in the core file. It is not practical
-	 * to read the GB size file into a user space buffer, Given the
-	 * fact that we don't use any info from that.
-	 */
-	elf_flags |= ELF_SKIP_FILESZ_CHECK;
-	result = build_elf_core_info(buf, size, &ehdr, elf_flags);
-	if (result < 0) {
-		/* Perhaps KCORE_ELF_HEADERS_SIZE is too small? */
-		fprintf(stderr, "ELF core (kcore) parse failed\n");
-		return -1;
-	}
-
-	end_phdr = &ehdr.e_phdr[ehdr.e_phnum];
-
-	/* Search for the real PAGE_OFFSET when KASLR memory randomization
-	 * is enabled */
-	if (get_kernel_sym("page_offset_base") != 0) {
-		for(phdr = ehdr.e_phdr; phdr != end_phdr; phdr++) {
-			if (phdr->p_type == PT_LOAD) {
-				vaddr = phdr->p_vaddr & pud_mask;
-				if (lowest_vaddr == 0 || lowest_vaddr > vaddr)
-					lowest_vaddr = vaddr;
-			}
-		}
-		if (lowest_vaddr != 0)
-			elf_info->page_offset = lowest_vaddr;
-	}
+	end_phdr = &ehdr->e_phdr[ehdr->e_phnum];
 
 	/* Traverse through the Elf headers and find the region where
 	 * _stext symbol is located in. That's where kernel is mapped */
 	stext_sym = get_kernel_sym("_stext");
-	for(phdr = ehdr.e_phdr; stext_sym && phdr != end_phdr; phdr++) {
+	for(phdr = ehdr->e_phdr; stext_sym && phdr != end_phdr; phdr++) {
 		if (phdr->p_type == PT_LOAD) {
 			unsigned long long saddr = phdr->p_vaddr;
 			unsigned long long eaddr = phdr->p_vaddr + phdr->p_memsz;
@@ -223,7 +204,7 @@ static int get_kernel_vaddr_and_size(str
 	 * /proc/kallsyms, Traverse through the Elf headers again and
 	 * find the region where kernel is mapped using hard-coded
 	 * kernel mapping boundries */
-	for(phdr = ehdr.e_phdr; phdr != end_phdr; phdr++) {
+	for(phdr = ehdr->e_phdr; phdr != end_phdr; phdr++) {
 		if (phdr->p_type == PT_LOAD) {
 			unsigned long long saddr = phdr->p_vaddr;
 			unsigned long long eaddr = phdr->p_vaddr + phdr->p_memsz;
@@ -887,6 +868,12 @@ int load_crashdump_segments(struct kexec
 	struct memory_range *mem_range, *memmap_p;
 	struct crash_elf_info elf_info;
 	unsigned kexec_arch;
+	char *buf;
+	off_t size;
+	struct mem_ehdr ehdr;
+	uint32_t elf_flags = 0;
+	const char kcore[] = "/proc/kcore";
+	int result;
 
 	memset(&elf_info, 0x0, sizeof(elf_info));
 
@@ -943,13 +930,32 @@ int load_crashdump_segments(struct kexec
 		elf_info.class = ELFCLASS64;
 	}
 
-	if (get_kernel_page_offset(info, &elf_info))
+	buf = slurp_file_len(kcore, KCORE_ELF_HEADERS_SIZE, &size);
+	if (!buf) {
+		fprintf(stderr, "Cannot read %s: %s\n", kcore, strerror(errno));
+		return -1;
+	}
+
+	/* Don't perform checks to make sure stated phdrs and shdrs are
+	 * actually present in the core file. It is not practical
+	 * to read the GB size file into a user space buffer, Given the
+	 * fact that we don't use any info from that.
+	 */
+	elf_flags |= ELF_SKIP_FILESZ_CHECK;
+	result = build_elf_core_info(buf, size, &ehdr, elf_flags);
+	if (result < 0) {
+		/* Perhaps KCORE_ELF_HEADERS_SIZE is too small? */
+		fprintf(stderr, "ELF core (kcore) parse failed\n");
+		return -1;
+	}
+
+	if (get_kernel_page_offset(info, &elf_info, &ehdr))
 		return -1;
 
 	if (get_kernel_paddr(info, &elf_info))
 		return -1;
 
-	if (get_kernel_vaddr_and_size(info, &elf_info))
+	if (get_kernel_vaddr_and_size(info, &elf_info, &ehdr))
 		return -1;
 
 	/* Memory regions which panic kernel can safely use to boot into */


From panand at redhat.com  Thu Oct  6 23:41:40 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 7 Oct 2016 12:11:40 +0530
Subject: [PATCH v3 2/8] kexec: generalize and rename get_kernel_stext_sym()
In-Reply-To: <20161007041837.GC16400@dhcp-128-65.nay.redhat.com>
References: <20160907043401.6403-1-takahiro.akashi@linaro.org>
 <20160907043401.6403-3-takahiro.akashi@linaro.org>
 <b88cbd6b-923d-d0c9-ce23-b9ef99aca256@gmail.com>
 <20161007041837.GC16400@dhcp-128-65.nay.redhat.com>
Message-ID: <CAHB_GuqmVetgyznpU_9ARDDbzCrmcKAn7b1_F8Z7XKdvq-b=qQ@mail.gmail.com>

Hi Dave,

On Fri, Oct 7, 2016 at 9:48 AM, Dave Young <dyoung at redhat.com> wrote:
>> >     /* Traverse through the Elf headers and find the region where
>> >      * _stext symbol is located in. That's where kernel is mapped */
>> > -   stext_sym = get_kernel_stext_sym();
>> > +   stext_sym = get_kernel_sym("stext");
>>
>>
>> I think this should be get_kernel_sym("_stext");
>>
>> Apart from that as Simon already mentioned, due to commit
>> 9f62cbd ("kexec/arch/i386: Add support for KASLR memory randomization")
>> this patch does not apply cleanly.
>
> Pratyush, I had a cleanup patch below, but I did not get time to test it
> so it is not ready to send out.
>
> The basic thought is to move the page_offset_base code to
> get_kernel_page_offset(), there is also another issue is for old kernel
> or kernel without kaslr built-in there will be an unnecessary error
> message but I have not get any idea how to fix it.
>

Are you talking about following error message:

"Cannot get kernel %s symbol address\n"

May be it can be changes as dbgprintf() rather than fprintf(stderr)

> Would you like to take below cleanup patch along with your next version?

I think, this patch series is for ARM64 support along with any generic
modifications needed by arm64 patches. Below modification is specific
to x86. So, better to send them separately.

> It is also fine to leave it as a future improvement to me.

OK.

>
> Thanks
> Dave
>
> ---
>  kexec/arch/i386/crashdump-x86.c |  158 ++++++++++++++++++++--------------------
>  1 file changed, 82 insertions(+), 76 deletions(-)
>
> --- kexec-tools.orig/kexec/arch/i386/crashdump-x86.c
> +++ kexec-tools/kexec/arch/i386/crashdump-x86.c
> @@ -54,10 +54,59 @@
>
>  extern struct arch_options_t arch_options;
>
> +/* Retrieve kernel symbol virtual address from /proc/kallsyms */
> +static unsigned long long get_kernel_sym(const char *symbol)
> +{
> +       const char *kallsyms = "/proc/kallsyms";
> +       char sym[128];
> +       char line[128];
> +       FILE *fp;
> +       unsigned long long vaddr;
> +       char type;
> +
> +       fp = fopen(kallsyms, "r");
> +       if (!fp) {
> +               fprintf(stderr, "Cannot open %s\n", kallsyms);
> +               return 0;
> +       }
> +
> +       while(fgets(line, sizeof(line), fp) != NULL) {
> +               if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
> +                       continue;
> +               if (strcmp(sym, symbol) == 0) {
> +                       dbgprintf("kernel symbol %s vaddr = %16llx\n", symbol, vaddr);
> +                       return vaddr;
> +               }
> +       }
> +
> +       fprintf(stderr, "Cannot get kernel %s symbol address\n", symbol);
> +
> +       return 0;
> +}
> +
>  static int get_kernel_page_offset(struct kexec_info *UNUSED(info),
> -                                 struct crash_elf_info *elf_info)
> +                                 struct crash_elf_info *elf_info,
> +                                 struct mem_ehdr *ehdr)
>  {
>         int kv;
> +       struct mem_phdr *phdr, *end_phdr;
> +       const unsigned long long pud_mask = ~((1 << 30) - 1);
> +       unsigned long long vaddr, lowest_vaddr = 0;
> +
> +       end_phdr = &ehdr->e_phdr[ehdr->e_phnum];
> +       /* Search for the real PAGE_OFFSET when KASLR memory randomization
> +        * is enabled */
> +       if (get_kernel_sym("page_offset_base") != 0) {
> +               for(phdr = ehdr->e_phdr; phdr != end_phdr; phdr++) {
> +                       if (phdr->p_type == PT_LOAD) {
> +                               vaddr = phdr->p_vaddr & pud_mask;
> +                               if (lowest_vaddr == 0 || lowest_vaddr > vaddr)

Although, it is just the copy of original code from one function to
another, but I think logic can be improved a bit here. Initialize
lowest_vaddr with ULONG_MAX and we can get rid of one check of
(lowest_vaddr == 0).

> +                                       lowest_vaddr = vaddr;
> +                       }
> +               }
> +               if (lowest_vaddr != 0)

And then here it should be (lowest_vaddr != ULONG_MAX)

> +                       elf_info->page_offset = lowest_vaddr;
> +       }
>
>         if (elf_info->machine == EM_X86_64) {
>                 kv = kernel_version();
> @@ -102,35 +151,6 @@ static int get_kernel_paddr(struct kexec
>         return -1;
>  }
>
> -/* Retrieve kernel symbol virtual address from /proc/kallsyms */
> -static unsigned long long get_kernel_sym(const char *symbol)
> -{
> -       const char *kallsyms = "/proc/kallsyms";
> -       char sym[128];
> -       char line[128];
> -       FILE *fp;
> -       unsigned long long vaddr;
> -       char type;
> -
> -       fp = fopen(kallsyms, "r");
> -       if (!fp) {
> -               fprintf(stderr, "Cannot open %s\n", kallsyms);
> -               return 0;
> -       }
> -
> -       while(fgets(line, sizeof(line), fp) != NULL) {
> -               if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
> -                       continue;
> -               if (strcmp(sym, symbol) == 0) {
> -                       dbgprintf("kernel symbol %s vaddr = %16llx\n", symbol, vaddr);
> -                       return vaddr;
> -               }
> -       }
> -
> -       fprintf(stderr, "Cannot get kernel %s symbol address\n", symbol);
> -       return 0;
> -}
> -
>  /* Retrieve info regarding virtual address kernel has been compiled for and
>   * size of the kernel from /proc/kcore. Current /proc/kcore parsing from
>   * from kexec-tools fails because of malformed elf notes. A kernel patch has
> @@ -139,19 +159,12 @@ static unsigned long long get_kernel_sym
>   * we should get rid of backward compatible code. */
>
>  static int get_kernel_vaddr_and_size(struct kexec_info *UNUSED(info),
> -                                    struct crash_elf_info *elf_info)
> +                                    struct crash_elf_info *elf_info,
> +                                    struct mem_ehdr *ehdr)
>  {
> -       int result;
> -       const char kcore[] = "/proc/kcore";
> -       char *buf;
> -       struct mem_ehdr ehdr;
>         struct mem_phdr *phdr, *end_phdr;
>         int align;
> -       off_t size;
> -       uint32_t elf_flags = 0;
>         uint64_t stext_sym;
> -       const unsigned long long pud_mask = ~((1 << 30) - 1);
> -       unsigned long long vaddr, lowest_vaddr = 0;
>
>         if (elf_info->machine != EM_X86_64)
>                 return 0;
> @@ -160,45 +173,13 @@ static int get_kernel_vaddr_and_size(str
>                 return 0;
>
>         align = getpagesize();
> -       buf = slurp_file_len(kcore, KCORE_ELF_HEADERS_SIZE, &size);
> -       if (!buf) {
> -               fprintf(stderr, "Cannot read %s: %s\n", kcore, strerror(errno));
> -               return -1;
> -       }
>
> -       /* Don't perform checks to make sure stated phdrs and shdrs are
> -        * actually present in the core file. It is not practical
> -        * to read the GB size file into a user space buffer, Given the
> -        * fact that we don't use any info from that.
> -        */
> -       elf_flags |= ELF_SKIP_FILESZ_CHECK;
> -       result = build_elf_core_info(buf, size, &ehdr, elf_flags);
> -       if (result < 0) {
> -               /* Perhaps KCORE_ELF_HEADERS_SIZE is too small? */
> -               fprintf(stderr, "ELF core (kcore) parse failed\n");
> -               return -1;
> -       }
> -
> -       end_phdr = &ehdr.e_phdr[ehdr.e_phnum];
> -
> -       /* Search for the real PAGE_OFFSET when KASLR memory randomization
> -        * is enabled */
> -       if (get_kernel_sym("page_offset_base") != 0) {
> -               for(phdr = ehdr.e_phdr; phdr != end_phdr; phdr++) {
> -                       if (phdr->p_type == PT_LOAD) {
> -                               vaddr = phdr->p_vaddr & pud_mask;
> -                               if (lowest_vaddr == 0 || lowest_vaddr > vaddr)
> -                                       lowest_vaddr = vaddr;
> -                       }
> -               }
> -               if (lowest_vaddr != 0)
> -                       elf_info->page_offset = lowest_vaddr;
> -       }
> +       end_phdr = &ehdr->e_phdr[ehdr->e_phnum];
>
>         /* Traverse through the Elf headers and find the region where
>          * _stext symbol is located in. That's where kernel is mapped */
>         stext_sym = get_kernel_sym("_stext");
> -       for(phdr = ehdr.e_phdr; stext_sym && phdr != end_phdr; phdr++) {
> +       for(phdr = ehdr->e_phdr; stext_sym && phdr != end_phdr; phdr++) {
>                 if (phdr->p_type == PT_LOAD) {
>                         unsigned long long saddr = phdr->p_vaddr;
>                         unsigned long long eaddr = phdr->p_vaddr + phdr->p_memsz;
> @@ -223,7 +204,7 @@ static int get_kernel_vaddr_and_size(str
>          * /proc/kallsyms, Traverse through the Elf headers again and
>          * find the region where kernel is mapped using hard-coded
>          * kernel mapping boundries */
> -       for(phdr = ehdr.e_phdr; phdr != end_phdr; phdr++) {
> +       for(phdr = ehdr->e_phdr; phdr != end_phdr; phdr++) {
>                 if (phdr->p_type == PT_LOAD) {
>                         unsigned long long saddr = phdr->p_vaddr;
>                         unsigned long long eaddr = phdr->p_vaddr + phdr->p_memsz;
> @@ -887,6 +868,12 @@ int load_crashdump_segments(struct kexec
>         struct memory_range *mem_range, *memmap_p;
>         struct crash_elf_info elf_info;
>         unsigned kexec_arch;
> +       char *buf;
> +       off_t size;
> +       struct mem_ehdr ehdr;
> +       uint32_t elf_flags = 0;
> +       const char kcore[] = "/proc/kcore";
> +       int result;
>
>         memset(&elf_info, 0x0, sizeof(elf_info));
>
> @@ -943,13 +930,32 @@ int load_crashdump_segments(struct kexec
>                 elf_info.class = ELFCLASS64;
>         }
>
> -       if (get_kernel_page_offset(info, &elf_info))
> +       buf = slurp_file_len(kcore, KCORE_ELF_HEADERS_SIZE, &size);
> +       if (!buf) {
> +               fprintf(stderr, "Cannot read %s: %s\n", kcore, strerror(errno));
> +               return -1;
> +       }
> +
> +       /* Don't perform checks to make sure stated phdrs and shdrs are
> +        * actually present in the core file. It is not practical
> +        * to read the GB size file into a user space buffer, Given the
> +        * fact that we don't use any info from that.
> +        */
> +       elf_flags |= ELF_SKIP_FILESZ_CHECK;
> +       result = build_elf_core_info(buf, size, &ehdr, elf_flags);
> +       if (result < 0) {
> +               /* Perhaps KCORE_ELF_HEADERS_SIZE is too small? */
> +               fprintf(stderr, "ELF core (kcore) parse failed\n");
> +               return -1;
> +       }
> +
> +       if (get_kernel_page_offset(info, &elf_info, &ehdr))
>                 return -1;
>
>         if (get_kernel_paddr(info, &elf_info))
>                 return -1;
>
> -       if (get_kernel_vaddr_and_size(info, &elf_info))
> +       if (get_kernel_vaddr_and_size(info, &elf_info, &ehdr))
>                 return -1;
>
>         /* Memory regions which panic kernel can safely use to boot into */

~Pratyush


From panand at redhat.com  Thu Oct  6 23:44:39 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 7 Oct 2016 12:14:39 +0530
Subject: [PATCH v3 2/8] kexec: generalize and rename get_kernel_stext_sym()
In-Reply-To: <b88cbd6b-923d-d0c9-ce23-b9ef99aca256@gmail.com>
References: <20160907043401.6403-1-takahiro.akashi@linaro.org>
 <20160907043401.6403-3-takahiro.akashi@linaro.org>
 <b88cbd6b-923d-d0c9-ce23-b9ef99aca256@gmail.com>
Message-ID: <CAHB_Guoa+7Gnas59TRwKbqXT2b40hj30PzkEVYMse6oT3nu1Gg@mail.gmail.com>

On Thu, Oct 6, 2016 at 6:58 PM, Matthias Brugger <matthias.bgg at gmail.com> wrote:
> On 09/07/2016 06:33 AM, AKASHI Takahiro wrote:
>>
>> From: Pratyush Anand <panand at redhat.com>
>>
>> get_kernel_stext_sym() has been defined for both arm and i386. Other
>> architecture might need some other kernel symbol address. Therefore
>> rewrite
>> this function as generic function to get any kernel symbol address.
>>
>> More over, kallsyms is not arch specific representation, therefore have
>> common function for all arches.
>>
>> Signed-off-by: Pratyush Anand <panand at redhat.com>
>> [created symbols.c]
>> Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
>> ---
>>  kexec/Makefile                  |  1 +
>>  kexec/arch/arm/crashdump-arm.c  | 40
>> +---------------------------------------
>>  kexec/arch/i386/crashdump-x86.c | 32 +-------------------------------
>>  kexec/kexec.h                   |  2 ++
>>  kexec/symbols.c                 | 41
>> +++++++++++++++++++++++++++++++++++++++++
>>  5 files changed, 46 insertions(+), 70 deletions(-)
>>  create mode 100644 kexec/symbols.c
>>
>> diff --git a/kexec/Makefile b/kexec/Makefile
>> index 39f365f..2b4fb3d 100644
>> --- a/kexec/Makefile
>> +++ b/kexec/Makefile
>> @@ -26,6 +26,7 @@ KEXEC_SRCS_base += kexec/kernel_version.c
>>  KEXEC_SRCS_base += kexec/lzma.c
>>  KEXEC_SRCS_base += kexec/zlib.c
>>  KEXEC_SRCS_base += kexec/kexec-xen.c
>> +KEXEC_SRCS_base += kexec/symbols.c
>>
>>  KEXEC_GENERATED_SRCS += $(PURGATORY_HEX_C)
>>
>> diff --git a/kexec/arch/arm/crashdump-arm.c
>> b/kexec/arch/arm/crashdump-arm.c
>> index 4a89b5e..2bc898b 100644
>> --- a/kexec/arch/arm/crashdump-arm.c
>> +++ b/kexec/arch/arm/crashdump-arm.c
>> @@ -73,48 +73,10 @@ static struct crash_elf_info elf_info = {
>>
>>  extern unsigned long long user_page_offset;
>>
>> -/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */
>> -static unsigned long long get_kernel_stext_sym(void)
>> -{
>> -       const char *kallsyms = "/proc/kallsyms";
>> -       const char *stext = "_stext";
>> -       char sym[128];
>> -       char line[128];
>> -       FILE *fp;
>> -       unsigned long long vaddr = 0;
>> -       char type;
>> -
>> -       fp = fopen(kallsyms, "r");
>> -       if (!fp) {
>> -               fprintf(stderr, "Cannot open %s\n", kallsyms);
>> -               return 0;
>> -       }
>> -
>> -       while(fgets(line, sizeof(line), fp) != NULL) {
>> -               unsigned long long addr;
>> -
>> -               if (sscanf(line, "%Lx %c %s", &addr, &type, sym) != 3)
>> -                       continue;
>> -
>> -               if (strcmp(sym, stext) == 0) {
>> -                       dbgprintf("kernel symbol %s vaddr = %#llx\n",
>> stext, addr);
>> -                       vaddr = addr;
>> -                       break;
>> -               }
>> -       }
>> -
>> -       fclose(fp);
>> -
>> -       if (vaddr == 0)
>> -               fprintf(stderr, "Cannot get kernel %s symbol address\n",
>> stext);
>> -
>> -       return vaddr;
>> -}
>> -
>>  static int get_kernel_page_offset(struct kexec_info *info,
>>                 struct crash_elf_info *elf_info)
>>  {
>> -       unsigned long long stext_sym_addr = get_kernel_stext_sym();
>> +       unsigned long long stext_sym_addr = get_kernel_sym("stext");
>>         if (stext_sym_addr == 0) {
>>                 if (user_page_offset != (-1ULL)) {
>>                         elf_info->page_offset = user_page_offset;
>> diff --git a/kexec/arch/i386/crashdump-x86.c
>> b/kexec/arch/i386/crashdump-x86.c
>> index bbc0f35..664eb3b 100644
>> --- a/kexec/arch/i386/crashdump-x86.c
>> +++ b/kexec/arch/i386/crashdump-x86.c
>> @@ -102,36 +102,6 @@ static int get_kernel_paddr(struct kexec_info
>> *UNUSED(info),
>>         return -1;
>>  }
>>
>> -/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */
>> -static unsigned long long get_kernel_stext_sym(void)
>> -{
>> -       const char *kallsyms = "/proc/kallsyms";
>> -       const char *stext = "_stext";
>> -       char sym[128];
>> -       char line[128];
>> -       FILE *fp;
>> -       unsigned long long vaddr;
>> -       char type;
>> -
>> -       fp = fopen(kallsyms, "r");
>> -       if (!fp) {
>> -               fprintf(stderr, "Cannot open %s\n", kallsyms);
>> -               return 0;
>> -       }
>> -
>> -       while(fgets(line, sizeof(line), fp) != NULL) {
>> -               if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3)
>> -                       continue;
>> -               if (strcmp(sym, stext) == 0) {
>> -                       dbgprintf("kernel symbol %s vaddr = %16llx\n",
>> stext, vaddr);
>> -                       return vaddr;
>> -               }
>> -       }
>> -
>> -       fprintf(stderr, "Cannot get kernel %s symbol address\n", stext);
>> -       return 0;
>> -}
>> -
>>  /* Retrieve info regarding virtual address kernel has been compiled for
>> and
>>   * size of the kernel from /proc/kcore. Current /proc/kcore parsing from
>>   * from kexec-tools fails because of malformed elf notes. A kernel patch
>> has
>> @@ -182,7 +152,7 @@ static int get_kernel_vaddr_and_size(struct kexec_info
>> *UNUSED(info),
>>
>>         /* Traverse through the Elf headers and find the region where
>>          * _stext symbol is located in. That's where kernel is mapped */
>> -       stext_sym = get_kernel_stext_sym();
>> +       stext_sym = get_kernel_sym("stext");
>
>
>
> I think this should be get_kernel_sym("_stext");

OK.

>
> Apart from that as Simon already mentioned, due to commit
> 9f62cbd ("kexec/arch/i386: Add support for KASLR memory randomization")
> this patch does not apply cleanly.
>

Will rebase with latest.

Thanks for your review.

~Pratyush


From jolsa at redhat.com  Thu Oct  6 23:49:27 2016
From: jolsa at redhat.com (Jiri Olsa)
Date: Fri, 7 Oct 2016 08:49:27 +0200
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
In-Reply-To: <57F66CF7.7040204@redhat.com>
References: <1475514432-27682-1-git-send-email-prarit@redhat.com>
 <alpine.DEB.2.20.1610041241160.7712@nanos>
 <57F39C09.10001@redhat.com>
 <alpine.DEB.2.20.1610041628120.5049@nanos>
 <20161005161455.GA26029@krava> <57F66CF7.7040204@redhat.com>
Message-ID: <20161007064927.GA2200@krava>

On Thu, Oct 06, 2016 at 11:25:43AM -0400, Prarit Bhargava wrote:
> 
> 
> On 10/05/2016 12:14 PM, Jiri Olsa wrote:
> > On Tue, Oct 04, 2016 at 04:38:16PM +0200, Thomas Gleixner wrote:
> >> On Tue, 4 Oct 2016, Prarit Bhargava wrote:
> >>> On 10/04/2016 06:58 AM, Thomas Gleixner wrote:
> >>>> While it is the right thing to initialize the package map in that case, it
> >>>> still papers over a robustness issue in the uncore code, which needs to be
> >>>> fixed first.
> >>>
> >>> I will include a separate patch with an error check for pkg == 0xffff in the
> >>> uncore code.
> >>
> >> 0xffff? That won't help. The id returned is -1 if the entry is not
> >> initialized. And aside of that just patching that particular place is not
> >> helping as the uncore code and also rapl is relying on the package map
> >> being populated.
> >>
> >> So we need a sanity check in the initialization code which prevents any of
> >> this being executed.
> > 
> > I still need to test this, but how about something like this?
> > 
> > thanks,
> > jirka
> > 
> > 
> > ---
> > diff --git a/arch/x86/events/intel/rapl.c b/arch/x86/events/intel/rapl.c
> > index 28865938aadf..61d087a2f25d 100644
> > --- a/arch/x86/events/intel/rapl.c
> > +++ b/arch/x86/events/intel/rapl.c
> > @@ -598,8 +598,13 @@ static int rapl_cpu_online(unsigned int cpu)
> >  
> >  static int rapl_cpu_prepare(unsigned int cpu)
> >  {
> > -	struct rapl_pmu *pmu = cpu_to_rapl_pmu(cpu);
> > +	struct rapl_pmu *pmu;
> > +	int pkg = topology_logical_package_id(cpu);
> > +
> > +	if (WARN_ON(pkg == -1))
> > +		return -EINVAL;
> >  
> > +	pmu = cpu_to_rapl_pmu(cpu);
> >  	if (pmu)
> >  		return 0;
> 
> I thought about doing this but it seems like every time some driver uses
> topology_logical_package_id() the driver would have to replicate the error
> checking code.

hm, unless we guarantee topology_logical_package_id always
returns sane values I dont see another way

jirka


From tglx at linutronix.de  Fri Oct  7 01:02:23 2016
From: tglx at linutronix.de (Thomas Gleixner)
Date: Fri, 7 Oct 2016 10:02:23 +0200 (CEST)
Subject: [PATCH] arch/x86: Fix kdump on x86 with physically hotadded CPUs
In-Reply-To: <20161007064927.GA2200@krava>
References: <1475514432-27682-1-git-send-email-prarit@redhat.com>
 <alpine.DEB.2.20.1610041241160.7712@nanos> <57F39C09.10001@redhat.com>
 <alpine.DEB.2.20.1610041628120.5049@nanos> <20161005161455.GA26029@krava>
 <57F66CF7.7040204@redhat.com> <20161007064927.GA2200@krava>
Message-ID: <alpine.DEB.2.20.1610070958320.4920@nanos>

On Fri, 7 Oct 2016, Jiri Olsa wrote:
> On Thu, Oct 06, 2016 at 11:25:43AM -0400, Prarit Bhargava wrote:
> > I thought about doing this but it seems like every time some driver uses
> > topology_logical_package_id() the driver would have to replicate the error
> > checking code.
> 
> hm, unless we guarantee topology_logical_package_id always
> returns sane values I dont see another way

I did some deeper investigation. So with prarits patch there is only one
possibility left to end up with an empty package id:

SMP Kernel on UP Machine, which has neither ACPI nor MADT. But those
machines are not a problem because they don't use any drivers which would
make use of it. Aside of that for UP we just can set the node of the cpu to
0 and be done with it. I'll pick up Prarits patch and amend it.

Thanks,

	tglx


From sagar.borikar at gmail.com  Sat Oct  8 06:04:28 2016
From: sagar.borikar at gmail.com (Sagar Borikar)
Date: Sat, 8 Oct 2016 06:04:28 -0700
Subject: MIPS little endian support for kexec-tools
Message-ID: <CAFwMWxs_r3VyBqE+r6VsLv1-Y=oxby=24NJ_+jEWShbEmdrfQA@mail.gmail.com>

Hi,

I am porting kexec on MIPS CPU which is running in little endian mode.
While setting up kexec, I see that the definitions of crash elf
headers are only for big endian MIPS. The elf header populated by the
crashdump-mips.c is for big endian.
Is there support for little endian MIPS in kexec tools?

Thanks
Sagar


From geoff at infradead.org  Mon Oct 10 14:22:59 2016
From: geoff at infradead.org (Geoff Levand)
Date: Mon, 10 Oct 2016 21:22:59 +0000
Subject: [PATCH 2/2] arm64: Add missing kexec dist files
In-Reply-To: <cover.1476134309.git.geoff@infradead.org>
References: <cover.1476134309.git.geoff@infradead.org>
Message-ID: <3552a3e85a910688d932535549b35354a54927ad.1476134309.git.geoff@infradead.org>

Signed-off-by: Geoff Levand <geoff at infradead.org>
---
 kexec/arch/arm64/Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kexec/arch/arm64/Makefile b/kexec/arch/arm64/Makefile
index d729df8..74b677f 100644
--- a/kexec/arch/arm64/Makefile
+++ b/kexec/arch/arm64/Makefile
@@ -20,7 +20,9 @@ arm64_VIRT_TO_PHYS =
 arm64_PHYS_TO_VIRT =
 
 dist += $(arm64_KEXEC_SRCS) \
+	kexec/arch/arm64/include/arch/options.h \
 	kexec/arch/arm64/crashdump-arm64.h \
+	kexec/arch/arm64/image-header.h \
 	kexec/arch/arm64/kexec-arm64.h \
 	kexec/arch/arm64/Makefile
 
-- 
2.7.4



From geoff at infradead.org  Mon Oct 10 14:22:58 2016
From: geoff at infradead.org (Geoff Levand)
Date: Mon, 10 Oct 2016 21:22:58 +0000
Subject: [PATCH 1/2] arm64: Cleanup kexec Makefile
In-Reply-To: <cover.1476134309.git.geoff@infradead.org>
References: <cover.1476134309.git.geoff@infradead.org>
Message-ID: <baa3da2fbfc708ee95cf96231ac92f98f8b9de29.1476134309.git.geoff@infradead.org>

Put files in alphabetical order, reformat whitspace.

Signed-off-by: Geoff Levand <geoff at infradead.org>
---
 kexec/arch/arm64/Makefile | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/kexec/arch/arm64/Makefile b/kexec/arch/arm64/Makefile
index 37414dc..d729df8 100644
--- a/kexec/arch/arm64/Makefile
+++ b/kexec/arch/arm64/Makefile
@@ -1,17 +1,18 @@
 
 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_FS2DT_INCLUDE += \
+	-include $(srcdir)/kexec/arch/arm64/crashdump-arm64.h \
+	-include $(srcdir)/kexec/arch/arm64/kexec-arm64.h
 
 arm64_DT_OPS += kexec/dt-ops.c
 
 arm64_CPPFLAGS += -I $(srcdir)/kexec/
 
 arm64_KEXEC_SRCS += \
+	kexec/arch/arm64/crashdump-arm64.c \
 	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
+	kexec/arch/arm64/kexec-image-arm64.c
 
 arm64_ARCH_REUSE_INITRD =
 arm64_ADD_SEGMENT =
@@ -19,9 +20,9 @@ arm64_VIRT_TO_PHYS =
 arm64_PHYS_TO_VIRT =
 
 dist += $(arm64_KEXEC_SRCS) \
-	kexec/arch/arm64/Makefile \
+	kexec/arch/arm64/crashdump-arm64.h \
 	kexec/arch/arm64/kexec-arm64.h \
-	kexec/arch/arm64/crashdump-arm64.h
+	kexec/arch/arm64/Makefile
 
 ifdef HAVE_LIBFDT
 
-- 
2.7.4




From geoff at infradead.org  Mon Oct 10 14:22:58 2016
From: geoff at infradead.org (Geoff Levand)
Date: Mon, 10 Oct 2016 21:22:58 +0000
Subject: [PATCH 0/2] arm64 kexec-tools fixups
Message-ID: <cover.1476134309.git.geoff@infradead.org>

Hi Simon,

Fixes for 'make tarball'.  Please apply.

-Geoff

The following changes since commit 6e8804f9ca67bee65aedd5e1cdf504737ab5c7ed:

  multiboot: Use the "reserved" type for non-ram zones (2016-10-07 11:54:44 +0900)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/geoff/kexec-tools.git for-merge-arm64-dist

for you to fetch changes up to 3552a3e85a910688d932535549b35354a54927ad:

  arm64: Add missing kexec dist files (2016-10-10 14:15:21 -0700)

----------------------------------------------------------------
Geoff Levand (2):
      arm64: Cleanup kexec Makefile
      arm64: Add missing kexec dist files

 kexec/arch/arm64/Makefile | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

-- 
2.7.4



From bhe at redhat.com  Tue Oct 11 00:41:11 2016
From: bhe at redhat.com (Baoquan He)
Date: Tue, 11 Oct 2016 15:41:11 +0800
Subject: [PATCH] kexec: Export memory sections virtual addresses to
 vmcoreinfo
In-Reply-To: <877f9lckbq.fsf@x220.int.ebiederm.org>
References: <1475743561-23912-1-git-send-email-bhe@redhat.com>
 <877f9lckbq.fsf@x220.int.ebiederm.org>
Message-ID: <20161011074111.GD11185@x1>

Hi Eric,

Thanks a lot for your reviewing! Sorry for late reply.

On 10/06/16 at 03:07pm, Eric W. Biederman wrote:
> Baoquan He <bhe at redhat.com> writes:
> 
> > KASLR memory randomization can randomize the base of the physical memory
> > mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap
> > (VMEMMAP_START). These need be exported to VMCOREINFO so that user space
> > utility, mainly makedumpfile can use them to identify the base of each
> > memory section. Here using VMCOREINFO_NUMBER we can reuse the existing
> > struct number_table in makedumpfile to import data easily.
> >
> > Since they are related to x86_64 only, put them into
> > arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE
> > together since it's also for x86_64 only.
> 
> *Scratches my head*  I would have thought this information would have
> better fit in the ELF header.  Where it actually has a field for virtual
> address.  It also has a field for physical address, and a third field
> for offset in the file (which is where the kdump finds these things in
> memory aftewards).
> 
> Why do we need need more magic vmcoreinfo to handle this?

Previously in x86_64, values of PAGE_OFFSET, VMALLOC and VMEMMAP are
fixed, makedumpfile also hard codes them.

In kexec-tools, we try to get page_offset_base from /proc/kallsyms or
search it from /proc/kcore elf header with the help of virtual address
of symbol _stext. Then we save it into p_vaddr of kernel text program
segment. In kdump kernel, we may assume kernel text has the biggest
starting virtual address and search it from vmcore elf header. But I
can't think of a way to get the starting virtual address of vmalloc and
vmemmap which are necessary for makedumpfile analysis.

So it's necessary to add them into VMCOREINFO to let makedumpfile know.

Thanks
Baoquan


From dyoung at redhat.com  Tue Oct 11 01:19:21 2016
From: dyoung at redhat.com (Dave Young)
Date: Tue, 11 Oct 2016 16:19:21 +0800
Subject: [PATCH] kexec: Export memory sections virtual addresses to
 vmcoreinfo
In-Reply-To: <20161011074111.GD11185@x1>
References: <1475743561-23912-1-git-send-email-bhe@redhat.com>
 <877f9lckbq.fsf@x220.int.ebiederm.org> <20161011074111.GD11185@x1>
Message-ID: <20161011081921.GA21765@dhcp-128-65.nay.redhat.com>

On 10/11/16 at 03:41pm, Baoquan He wrote:
> Hi Eric,
> 
> Thanks a lot for your reviewing! Sorry for late reply.
> 
> On 10/06/16 at 03:07pm, Eric W. Biederman wrote:
> > Baoquan He <bhe at redhat.com> writes:
> > 
> > > KASLR memory randomization can randomize the base of the physical memory
> > > mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap
> > > (VMEMMAP_START). These need be exported to VMCOREINFO so that user space
> > > utility, mainly makedumpfile can use them to identify the base of each
> > > memory section. Here using VMCOREINFO_NUMBER we can reuse the existing
> > > struct number_table in makedumpfile to import data easily.
> > >
> > > Since they are related to x86_64 only, put them into
> > > arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE
> > > together since it's also for x86_64 only.
> > 
> > *Scratches my head*  I would have thought this information would have
> > better fit in the ELF header.  Where it actually has a field for virtual
> > address.  It also has a field for physical address, and a third field
> > for offset in the file (which is where the kdump finds these things in
> > memory aftewards).
> > 
> > Why do we need need more magic vmcoreinfo to handle this?
> 
> Previously in x86_64, values of PAGE_OFFSET, VMALLOC and VMEMMAP are
> fixed, makedumpfile also hard codes them.
> 
> In kexec-tools, we try to get page_offset_base from /proc/kallsyms or
> search it from /proc/kcore elf header with the help of virtual address
> of symbol _stext. Then we save it into p_vaddr of kernel text program
> segment. In kdump kernel, we may assume kernel text has the biggest
> starting virtual address and search it from vmcore elf header. But I
> can't think of a way to get the starting virtual address of vmalloc and
> vmemmap which are necessary for makedumpfile analysis.
> 
> So it's necessary to add them into VMCOREINFO to let makedumpfile know.

PAGE_OFFSET can be get via vaddr - paddr from elf pt_loads so only
VMALLOC_BASE and VMEMMAP_BASE is necessary..

Thanks
Dave


From dyoung at redhat.com  Tue Oct 11 01:43:24 2016
From: dyoung at redhat.com (Dave Young)
Date: Tue, 11 Oct 2016 16:43:24 +0800
Subject: [PATCH] kexec: Export memory sections virtual addresses to
 vmcoreinfo
In-Reply-To: <20161011081921.GA21765@dhcp-128-65.nay.redhat.com>
References: <1475743561-23912-1-git-send-email-bhe@redhat.com>
 <877f9lckbq.fsf@x220.int.ebiederm.org> <20161011074111.GD11185@x1>
 <20161011081921.GA21765@dhcp-128-65.nay.redhat.com>
Message-ID: <20161011084324.GA14404@dhcp-128-65.nay.redhat.com>

On 10/11/16 at 04:19pm, Dave Young wrote:
> On 10/11/16 at 03:41pm, Baoquan He wrote:
> > Hi Eric,
> > 
> > Thanks a lot for your reviewing! Sorry for late reply.
> > 
> > On 10/06/16 at 03:07pm, Eric W. Biederman wrote:
> > > Baoquan He <bhe at redhat.com> writes:
> > > 
> > > > KASLR memory randomization can randomize the base of the physical memory
> > > > mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap
> > > > (VMEMMAP_START). These need be exported to VMCOREINFO so that user space
> > > > utility, mainly makedumpfile can use them to identify the base of each
> > > > memory section. Here using VMCOREINFO_NUMBER we can reuse the existing
> > > > struct number_table in makedumpfile to import data easily.
> > > >
> > > > Since they are related to x86_64 only, put them into
> > > > arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE
> > > > together since it's also for x86_64 only.
> > > 
> > > *Scratches my head*  I would have thought this information would have
> > > better fit in the ELF header.  Where it actually has a field for virtual
> > > address.  It also has a field for physical address, and a third field
> > > for offset in the file (which is where the kdump finds these things in
> > > memory aftewards).
> > > 
> > > Why do we need need more magic vmcoreinfo to handle this?
> > 
> > Previously in x86_64, values of PAGE_OFFSET, VMALLOC and VMEMMAP are
> > fixed, makedumpfile also hard codes them.
> > 
> > In kexec-tools, we try to get page_offset_base from /proc/kallsyms or
> > search it from /proc/kcore elf header with the help of virtual address
> > of symbol _stext. Then we save it into p_vaddr of kernel text program
> > segment. In kdump kernel, we may assume kernel text has the biggest
> > starting virtual address and search it from vmcore elf header. But I
> > can't think of a way to get the starting virtual address of vmalloc and
> > vmemmap which are necessary for makedumpfile analysis.
> > 
> > So it's necessary to add them into VMCOREINFO to let makedumpfile know.
> 
> PAGE_OFFSET can be get via vaddr - paddr from elf pt_loads so only
> VMALLOC_BASE and VMEMMAP_BASE is necessary..

Besides of these, since kernel module is randomized as well I wonder if
it need special handling, does it work?

> 
> Thanks
> Dave
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From mbrugger at suse.com  Tue Oct 11 03:20:41 2016
From: mbrugger at suse.com (Matthias Brugger)
Date: Tue, 11 Oct 2016 12:20:41 +0200
Subject: [PATCH 0/2] arm64 kexec-tools fixups
In-Reply-To: <cover.1476134309.git.geoff@infradead.org>
References: <cover.1476134309.git.geoff@infradead.org>
Message-ID: <ebe32436-6069-06c5-702f-d435d0dacd48@suse.com>



On 10/10/2016 11:22 PM, Geoff Levand wrote:
> Hi Simon,
>
> Fixes for 'make tarball'.  Please apply.
>
> -Geoff
>
> The following changes since commit 6e8804f9ca67bee65aedd5e1cdf504737ab5c7ed:
>
>   multiboot: Use the "reserved" type for non-ram zones (2016-10-07 11:54:44 +0900)
>
> are available in the git repository at:
>
>   git://git.kernel.org/pub/scm/linux/kernel/git/geoff/kexec-tools.git for-merge-arm64-dist
>
> for you to fetch changes up to 3552a3e85a910688d932535549b35354a54927ad:
>
>   arm64: Add missing kexec dist files (2016-10-10 14:15:21 -0700)
>
> ----------------------------------------------------------------
> Geoff Levand (2):
>       arm64: Cleanup kexec Makefile
>       arm64: Add missing kexec dist files
>
>  kexec/arch/arm64/Makefile | 15 +++++++++------
>  1 file changed, 9 insertions(+), 6 deletions(-)
>

Reviewed-by: Matthias Brugger <mbrugger at suse.com>


From bhe at redhat.com  Tue Oct 11 17:26:13 2016
From: bhe at redhat.com (Baoquan He)
Date: Wed, 12 Oct 2016 08:26:13 +0800
Subject: [PATCH] kexec: Export memory sections virtual addresses to
 vmcoreinfo
In-Reply-To: <20161011081921.GA21765@dhcp-128-65.nay.redhat.com>
References: <1475743561-23912-1-git-send-email-bhe@redhat.com>
 <877f9lckbq.fsf@x220.int.ebiederm.org> <20161011074111.GD11185@x1>
 <20161011081921.GA21765@dhcp-128-65.nay.redhat.com>
Message-ID: <20161012002613.GB21477@x1>

On 10/11/16 at 04:19pm, Dave Young wrote:
> On 10/11/16 at 03:41pm, Baoquan He wrote:
> > Hi Eric,
> > 
> > Thanks a lot for your reviewing! Sorry for late reply.
> > 
> > On 10/06/16 at 03:07pm, Eric W. Biederman wrote:
> > > Baoquan He <bhe at redhat.com> writes:
> > > 
> > > > KASLR memory randomization can randomize the base of the physical memory
> > > > mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap
> > > > (VMEMMAP_START). These need be exported to VMCOREINFO so that user space
> > > > utility, mainly makedumpfile can use them to identify the base of each
> > > > memory section. Here using VMCOREINFO_NUMBER we can reuse the existing
> > > > struct number_table in makedumpfile to import data easily.
> > > >
> > > > Since they are related to x86_64 only, put them into
> > > > arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE
> > > > together since it's also for x86_64 only.
> > > 
> > > *Scratches my head*  I would have thought this information would have
> > > better fit in the ELF header.  Where it actually has a field for virtual
> > > address.  It also has a field for physical address, and a third field
> > > for offset in the file (which is where the kdump finds these things in
> > > memory aftewards).
> > > 
> > > Why do we need need more magic vmcoreinfo to handle this?
> > 
> > Previously in x86_64, values of PAGE_OFFSET, VMALLOC and VMEMMAP are
> > fixed, makedumpfile also hard codes them.
> > 
> > In kexec-tools, we try to get page_offset_base from /proc/kallsyms or
> > search it from /proc/kcore elf header with the help of virtual address
> > of symbol _stext. Then we save it into p_vaddr of kernel text program
> > segment. In kdump kernel, we may assume kernel text has the biggest
> > starting virtual address and search it from vmcore elf header. But I
> > can't think of a way to get the starting virtual address of vmalloc and
> > vmemmap which are necessary for makedumpfile analysis.
> > 
> > So it's necessary to add them into VMCOREINFO to let makedumpfile know.
> 
> PAGE_OFFSET can be get via vaddr - paddr from elf pt_loads so only
> VMALLOC_BASE and VMEMMAP_BASE is necessary..

Well, yes, I was wrong. I wrongly thought of kernel text virtual address
when I wrote the reply.

So for PAGE_OFFSET we can exclude PT_NOTE and kernel text and calculate
PAGE_OFFSET via vaddr - paddr from crash memory program headers. Surely 
exporting is easier.

Thanks
Baoquan


From panand at redhat.com  Wed Oct 12 02:09:45 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 12 Oct 2016 14:39:45 +0530
Subject: [PATCH] kexec: Export memory sections virtual addresses to
 vmcoreinfo
In-Reply-To: <20161012002613.GB21477@x1>
References: <1475743561-23912-1-git-send-email-bhe@redhat.com>
 <877f9lckbq.fsf@x220.int.ebiederm.org> <20161011074111.GD11185@x1>
 <20161011081921.GA21765@dhcp-128-65.nay.redhat.com>
 <20161012002613.GB21477@x1>
Message-ID: <256e8ba2-4f92-36cf-ec5c-2502113922c6@redhat.com>



On Wednesday 12 October 2016 05:56 AM, Baoquan He wrote:
>> PAGE_OFFSET can be get via vaddr - paddr from elf pt_loads so only
>> > VMALLOC_BASE and VMEMMAP_BASE is necessary..
> Well, yes, I was wrong. I wrongly thought of kernel text virtual address
> when I wrote the reply

So, if you can get PAGE_OFFSET then, probably you do not need to know 
anything else.

I think, we can simplify makedumpfile code, where we do not need to 
depend on VMALLOC_START or VMEMMAP_START etc.

"If we know PAGE_OFFSET, we can read from swapper space. If we can read 
from swapper space, then we can know PA of any kernel VA, whether it is 
VMALLOC, or vmemmap or module or kernel text area."


In fact, I have cleanup patches for ARM64 [1], which take above approach 
and get rid of need of VMALLOC_START or VMEMMAP_START etc. I will be 
sending them upstream soon.

Probably, x86 can take the similar approach.

~Pratyush

[1] 
https://github.com/pratyushanand/makedumpfile/blob/arm64_devel/arch/arm64.c#L228



From bhe at redhat.com  Thu Oct 13 01:53:14 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 13 Oct 2016 16:53:14 +0800
Subject: [PATCH] kexec: Export memory sections virtual addresses to
 vmcoreinfo
In-Reply-To: <256e8ba2-4f92-36cf-ec5c-2502113922c6@redhat.com>
References: <1475743561-23912-1-git-send-email-bhe@redhat.com>
 <877f9lckbq.fsf@x220.int.ebiederm.org> <20161011074111.GD11185@x1>
 <20161011081921.GA21765@dhcp-128-65.nay.redhat.com>
 <20161012002613.GB21477@x1>
 <256e8ba2-4f92-36cf-ec5c-2502113922c6@redhat.com>
Message-ID: <20161013085314.GF11185@x1>

Hi Pratyush,

On 10/12/16 at 02:39pm, Pratyush Anand wrote:
> 
> 
> On Wednesday 12 October 2016 05:56 AM, Baoquan He wrote:
> > > PAGE_OFFSET can be get via vaddr - paddr from elf pt_loads so only
> > > > VMALLOC_BASE and VMEMMAP_BASE is necessary..
> > Well, yes, I was wrong. I wrongly thought of kernel text virtual address
> > when I wrote the reply
> 
> So, if you can get PAGE_OFFSET then, probably you do not need to know
> anything else.
> 
> I think, we can simplify makedumpfile code, where we do not need to depend
> on VMALLOC_START or VMEMMAP_START etc.
> 
> "If we know PAGE_OFFSET, we can read from swapper space. If we can read from
> swapper space, then we can know PA of any kernel VA, whether it is VMALLOC,
> or vmemmap or module or kernel text area."

Check makedumpfile code and re-think about this, it's really like you
said, we can convert VA to PA by swapper_pg_dir or init_level4_pgt. But the
reason why we have to involve VMALLOC_START and VMEMMAP_START is that in
x86_64 direct mapping and kernel text mapping are all linear mapping.
Linear mapping can let us do a very efficient translation from VA to
PA. Especially for page filtering, we need get PA of mm related data.
All of them need convert by swapper_pg_dir or init_level4_pgt, that's
inefficient, imagine the current system usually own many Tera bytes of
physical memory.

So here though we can pick up crash memory regions from elf program
header of vmcore and calculate the PAGE_OFFSET, we still need
VMALLOC_START and VMEMMAP_START.

Thanks
Baoquan
> 
> 
> In fact, I have cleanup patches for ARM64 [1], which take above approach and
> get rid of need of VMALLOC_START or VMEMMAP_START etc. I will be sending
> them upstream soon.
> 
> Probably, x86 can take the similar approach.
> 
> ~Pratyush
> 
> [1] https://github.com/pratyushanand/makedumpfile/blob/arm64_devel/arch/arm64.c#L228
> 


From horms at verge.net.au  Thu Oct 13 02:25:14 2016
From: horms at verge.net.au (Simon Horman)
Date: Thu, 13 Oct 2016 11:25:14 +0200
Subject: [PATCH 0/2] arm64 kexec-tools fixups
In-Reply-To: <ebe32436-6069-06c5-702f-d435d0dacd48@suse.com>
References: <cover.1476134309.git.geoff@infradead.org>
 <ebe32436-6069-06c5-702f-d435d0dacd48@suse.com>
Message-ID: <20161013092514.GP18804@verge.net.au>

On Tue, Oct 11, 2016 at 12:20:41PM +0200, Matthias Brugger wrote:
> 
> 
> On 10/10/2016 11:22 PM, Geoff Levand wrote:
> >Hi Simon,
> >
> >Fixes for 'make tarball'.  Please apply.
> >
> >-Geoff
> >
> >The following changes since commit 6e8804f9ca67bee65aedd5e1cdf504737ab5c7ed:
> >
> >  multiboot: Use the "reserved" type for non-ram zones (2016-10-07 11:54:44 +0900)
> >
> >are available in the git repository at:
> >
> >  git://git.kernel.org/pub/scm/linux/kernel/git/geoff/kexec-tools.git for-merge-arm64-dist
> >
> >for you to fetch changes up to 3552a3e85a910688d932535549b35354a54927ad:
> >
> >  arm64: Add missing kexec dist files (2016-10-10 14:15:21 -0700)
> >
> >----------------------------------------------------------------
> >Geoff Levand (2):
> >      arm64: Cleanup kexec Makefile
> >      arm64: Add missing kexec dist files
> >
> > kexec/arch/arm64/Makefile | 15 +++++++++------
> > 1 file changed, 9 insertions(+), 6 deletions(-)
> >
> 
> Reviewed-by: Matthias Brugger <mbrugger at suse.com>

Thanks, applied.


From dyoung at redhat.com  Thu Oct 13 20:13:04 2016
From: dyoung at redhat.com (Dave Young)
Date: Fri, 14 Oct 2016 11:13:04 +0800
Subject: [PATCH] kexec: Export memory sections virtual addresses to
 vmcoreinfo
In-Reply-To: <20161013085314.GF11185@x1>
References: <1475743561-23912-1-git-send-email-bhe@redhat.com>
 <877f9lckbq.fsf@x220.int.ebiederm.org> <20161011074111.GD11185@x1>
 <20161011081921.GA21765@dhcp-128-65.nay.redhat.com>
 <20161012002613.GB21477@x1>
 <256e8ba2-4f92-36cf-ec5c-2502113922c6@redhat.com>
 <20161013085314.GF11185@x1>
Message-ID: <20161014031304.GA3483@dhcp-128-65.nay.redhat.com>

On 10/13/16 at 04:53pm, Baoquan He wrote:
> Hi Pratyush,
> 
> On 10/12/16 at 02:39pm, Pratyush Anand wrote:
> > 
> > 
> > On Wednesday 12 October 2016 05:56 AM, Baoquan He wrote:
> > > > PAGE_OFFSET can be get via vaddr - paddr from elf pt_loads so only
> > > > > VMALLOC_BASE and VMEMMAP_BASE is necessary..
> > > Well, yes, I was wrong. I wrongly thought of kernel text virtual address
> > > when I wrote the reply
> > 
> > So, if you can get PAGE_OFFSET then, probably you do not need to know
> > anything else.
> > 
> > I think, we can simplify makedumpfile code, where we do not need to depend
> > on VMALLOC_START or VMEMMAP_START etc.
> > 
> > "If we know PAGE_OFFSET, we can read from swapper space. If we can read from
> > swapper space, then we can know PA of any kernel VA, whether it is VMALLOC,
> > or vmemmap or module or kernel text area."
> 
> Check makedumpfile code and re-think about this, it's really like you
> said, we can convert VA to PA by swapper_pg_dir or init_level4_pgt. But the
> reason why we have to involve VMALLOC_START and VMEMMAP_START is that in
> x86_64 direct mapping and kernel text mapping are all linear mapping.
> Linear mapping can let us do a very efficient translation from VA to
> PA. Especially for page filtering, we need get PA of mm related data.
> All of them need convert by swapper_pg_dir or init_level4_pgt, that's
> inefficient, imagine the current system usually own many Tera bytes of
> physical memory.
> 

Atsushi, what do you think about above concern?  Ideally we should do it
in userspace instead of add more symbols. Maybe do a test on large
memory machine is necessary.

> So here though we can pick up crash memory regions from elf program
> header of vmcore and calculate the PAGE_OFFSET, we still need
> VMALLOC_START and VMEMMAP_START.
> 
> Thanks
> Baoquan
> > 
> > 
> > In fact, I have cleanup patches for ARM64 [1], which take above approach and
> > get rid of need of VMALLOC_START or VMEMMAP_START etc. I will be sending
> > them upstream soon.
> > 
> > Probably, x86 can take the similar approach.
> > 
> > ~Pratyush
> > 
> > [1] https://github.com/pratyushanand/makedumpfile/blob/arm64_devel/arch/arm64.c#L228
> > 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec

Thanks
Dave


From gregkh at linuxfoundation.org  Fri Oct 14 05:27:12 2016
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Fri, 14 Oct 2016 14:27:12 +0200
Subject: [PATCH 4.8 26/37] arch/x86: Handle non enumerated CPU after physical
 hotplug
In-Reply-To: <20161014122549.411962735@linuxfoundation.org>
References: <20161014122549.411962735@linuxfoundation.org>
Message-ID: <20161014122553.581193322@linuxfoundation.org>

4.8-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Prarit Bhargava <prarit at redhat.com>

commit 2a51fe083eba7f99cbda72f5ef90cdf2f4df882c upstream.

When a CPU is physically added to a system then the MADT table is not
updated.

If subsequently a kdump kernel is started on that physically added CPU then
the ACPI enumeration fails to provide the information for this CPU which is
now the boot CPU of the kdump kernel.

As a consequence, generic_processor_info() is not invoked for that CPU so
the number of enumerated processors is 0 and none of the initializations,
including the logical package id management, are performed.

We have code which relies on the correctness of the logical package map and
other information which is initialized via generic_processor_info().
Executing such code will result in undefined behaviour or kernel crashes.

This problem applies only to the kdump kernel because a normal kexec will
switch to the original boot CPU, which is enumerated in MADT, before
jumping into the kexec kernel.

The boot code already has a check for num_processors equal 0 in
prefill_possible_map(). We can use that check as an indicator that the
enumeration of the boot CPU did not happen and invoke generic_processor_info()
for it. That initializes the relevant data for the boot CPU and therefore
prevents subsequent failure.

[ tglx: Refined the code and rewrote the changelog ]

Signed-off-by: Prarit Bhargava <prarit at redhat.com>
Fixes: 1f12e32f4cd5 ("x86/topology: Create logical package id")
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Len Brown <len.brown at intel.com>
Cc: Borislav Petkov <bp at suse.de>
Cc: Andi Kleen <ak at linux.intel.com>
Cc: Jiri Olsa <jolsa at redhat.com>
Cc: Juergen Gross <jgross at suse.com>
Cc: dyoung at redhat.com
Cc: Eric Biederman <ebiederm at xmission.com>
Cc: kexec at lists.infradead.org
Link: http://lkml.kernel.org/r/1475514432-27682-1-git-send-email-prarit at redhat.com
Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>

---
 arch/x86/kernel/smpboot.c |   18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1406,9 +1406,21 @@ __init void prefill_possible_map(void)
 {
 	int i, possible;
 
-	/* no processor from mptable or madt */
-	if (!num_processors)
-		num_processors = 1;
+	/* No boot processor was found in mptable or ACPI MADT */
+	if (!num_processors) {
+		int apicid = boot_cpu_physical_apicid;
+		int cpu = hard_smp_processor_id();
+
+		pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu);
+
+		/* Make sure boot cpu is enumerated */
+		if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
+		    apic->apic_id_valid(apicid))
+			generic_processor_info(apicid, boot_cpu_apic_version);
+
+		if (!num_processors)
+			num_processors = 1;
+	}
 
 	i = setup_max_cpus ?: 1;
 	if (setup_possible_cpus == -1) {




From gregkh at linuxfoundation.org  Fri Oct 14 05:55:07 2016
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Fri, 14 Oct 2016 14:55:07 +0200
Subject: [PATCH 4.7 23/31] arch/x86: Handle non enumerated CPU after physical
 hotplug
In-Reply-To: <20161014122715.235592611@linuxfoundation.org>
References: <20161014122715.235592611@linuxfoundation.org>
Message-ID: <20161014122716.194690765@linuxfoundation.org>

4.7-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Prarit Bhargava <prarit at redhat.com>

commit 2a51fe083eba7f99cbda72f5ef90cdf2f4df882c upstream.

When a CPU is physically added to a system then the MADT table is not
updated.

If subsequently a kdump kernel is started on that physically added CPU then
the ACPI enumeration fails to provide the information for this CPU which is
now the boot CPU of the kdump kernel.

As a consequence, generic_processor_info() is not invoked for that CPU so
the number of enumerated processors is 0 and none of the initializations,
including the logical package id management, are performed.

We have code which relies on the correctness of the logical package map and
other information which is initialized via generic_processor_info().
Executing such code will result in undefined behaviour or kernel crashes.

This problem applies only to the kdump kernel because a normal kexec will
switch to the original boot CPU, which is enumerated in MADT, before
jumping into the kexec kernel.

The boot code already has a check for num_processors equal 0 in
prefill_possible_map(). We can use that check as an indicator that the
enumeration of the boot CPU did not happen and invoke generic_processor_info()
for it. That initializes the relevant data for the boot CPU and therefore
prevents subsequent failure.

[ tglx: Refined the code and rewrote the changelog ]

Signed-off-by: Prarit Bhargava <prarit at redhat.com>
Fixes: 1f12e32f4cd5 ("x86/topology: Create logical package id")
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Len Brown <len.brown at intel.com>
Cc: Borislav Petkov <bp at suse.de>
Cc: Andi Kleen <ak at linux.intel.com>
Cc: Jiri Olsa <jolsa at redhat.com>
Cc: Juergen Gross <jgross at suse.com>
Cc: dyoung at redhat.com
Cc: Eric Biederman <ebiederm at xmission.com>
Cc: kexec at lists.infradead.org
Link: http://lkml.kernel.org/r/1475514432-27682-1-git-send-email-prarit at redhat.com
Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>

---
 arch/x86/kernel/smpboot.c |   18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1393,9 +1393,21 @@ __init void prefill_possible_map(void)
 {
 	int i, possible;
 
-	/* no processor from mptable or madt */
-	if (!num_processors)
-		num_processors = 1;
+	/* No boot processor was found in mptable or ACPI MADT */
+	if (!num_processors) {
+		int apicid = boot_cpu_physical_apicid;
+		int cpu = hard_smp_processor_id();
+
+		pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu);
+
+		/* Make sure boot cpu is enumerated */
+		if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
+		    apic->apic_id_valid(apicid))
+			generic_processor_info(apicid, boot_cpu_apic_version);
+
+		if (!num_processors)
+			num_processors = 1;
+	}
 
 	i = setup_max_cpus ?: 1;
 	if (setup_possible_cpus == -1) {




From rbilovol at cisco.com  Mon Oct 17 08:41:01 2016
From: rbilovol at cisco.com (Ruslan Bilovol)
Date: Mon, 17 Oct 2016 18:41:01 +0300
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <20160907042908.6232-1-takahiro.akashi@linaro.org>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
Message-ID: <3400bddc-9c6e-b69a-b57d-62921197bef9@cisco.com>

Hi,

On 09/07/2016 07:29 AM, AKASHI Takahiro wrote:
>      v26-specific note: After a comment from Rob[0], an idea of adding
>      "linux,usable-memory-range" was dropped. Instead, an existing
>      "reserved-memory" node will be used to limit usable memory ranges
>      on crash dump kernel.
>      This works not only on UEFI/ACPI systems but also on DT-only systems,
>      but if he really insists on using DT-specific "usable-memory" property,
>      I will post additional patches for kexec-tools. Those would be
>      redundant, though.
>      Even in that case, the kernel will not have to be changed.
>
> This patch series adds kdump support on arm64.
> There are some prerequisite patches [1],[2].
>
> To load a crash-dump kernel to the systems, a series of patches to
> kexec-tools, which have not yet been merged upstream, are needed.
> Please always use my latest kdump patches, v3 [3].
>
> To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
>    - crash utility (coming v7.1.6 or later) [4]
>      (Necessary patches have already been queued in the master.)
>
>
> [0] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/452582.html
> [1] "arm64: mark reserved memblock regions explicitly in iomem"
>      http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/450433.html
> [2] "efi: arm64: treat regions with WT/WC set but WB cleared as memory"
>      http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/451491.html
> [3] T.B.D.
> [4] https://github.com/crash-utility/crash.git

Are you going to rebase your patch series onto v4.9-rc1 tag soon? I see
that patches [1] and [2] are already in v4.9-rc1, but when tried to apply
this series, I've got conflict on first patch of the series ("arm64: kdump:
reserve memory for crash dump kernel"). I want to try arm64 kdump
patches again on my board, so I'm interested in this. The question is
whether I need to rebase it myself or you will do the same (and address
comments) soon.

Also I see Geoff published v6 of arm64 kexec-tools patches, so same
question is applicable to "(kexec-tools) arm64: add kdump support"
patch series.

Thanks,
Ruslan



From takahiro.akashi at linaro.org  Mon Oct 17 23:26:19 2016
From: takahiro.akashi at linaro.org (AKASHI Takahiro)
Date: Tue, 18 Oct 2016 15:26:19 +0900
Subject: [PATCH v26 0/7] arm64: add kdump support
In-Reply-To: <3400bddc-9c6e-b69a-b57d-62921197bef9@cisco.com>
References: <20160907042908.6232-1-takahiro.akashi@linaro.org>
 <3400bddc-9c6e-b69a-b57d-62921197bef9@cisco.com>
Message-ID: <20161018062617.GN19531@linaro.org>

Ruslan,

On Mon, Oct 17, 2016 at 06:41:01PM +0300, Ruslan Bilovol wrote:
> Hi,
> 
> On 09/07/2016 07:29 AM, AKASHI Takahiro wrote:
> >     v26-specific note: After a comment from Rob[0], an idea of adding
> >     "linux,usable-memory-range" was dropped. Instead, an existing
> >     "reserved-memory" node will be used to limit usable memory ranges
> >     on crash dump kernel.
> >     This works not only on UEFI/ACPI systems but also on DT-only systems,
> >     but if he really insists on using DT-specific "usable-memory" property,
> >     I will post additional patches for kexec-tools. Those would be
> >     redundant, though.
> >     Even in that case, the kernel will not have to be changed.
> >
> >This patch series adds kdump support on arm64.
> >There are some prerequisite patches [1],[2].
> >
> >To load a crash-dump kernel to the systems, a series of patches to
> >kexec-tools, which have not yet been merged upstream, are needed.
> >Please always use my latest kdump patches, v3 [3].
> >
> >To examine vmcore (/proc/vmcore) on a crash-dump kernel, you can use
> >   - crash utility (coming v7.1.6 or later) [4]
> >     (Necessary patches have already been queued in the master.)
> >
> >
> >[0] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/452582.html
> >[1] "arm64: mark reserved memblock regions explicitly in iomem"
> >     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/450433.html
> >[2] "efi: arm64: treat regions with WT/WC set but WB cleared as memory"
> >     http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/451491.html
> >[3] T.B.D.
> >[4] https://github.com/crash-utility/crash.git
> 
> Are you going to rebase your patch series onto v4.9-rc1 tag soon? I see

Yes, definitely as soon as possible! (actually I've done it.)
But before submitting a new version, I need to convince Rob (Herring)
that he would accept my old approach (v25) regarding specifying usable
memory for crash dump kernel:
   http://lists.infradead.org/pipermail/linux-arm-kernel/2016-September/459379.html 

> that patches [1] and [2] are already in v4.9-rc1, but when tried to apply
> this series, I've got conflict on first patch of the series ("arm64: kdump:
> reserve memory for crash dump kernel"). I want to try arm64 kdump
> patches again on my board, so I'm interested in this. The question is
> whether I need to rebase it myself or you will do the same (and address
> comments) soon.

Thank you for your interests and sorry for any inconvenience.

-Takahiro AKASHI

> Also I see Geoff published v6 of arm64 kexec-tools patches, so same
> question is applicable to "(kexec-tools) arm64: add kdump support"
> patch series.
> 
> Thanks,
> Ruslan
> 


From catalin.marinas at arm.com  Wed Oct 19 08:58:34 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Wed, 19 Oct 2016 16:58:34 +0100
Subject: [PATCH] arm64: Add support for additional relocations in the kexec
 purgatory code
Message-ID: <1476892714-27304-1-git-send-email-catalin.marinas@arm.com>

When compiling the kexec-tools with gcc6, the following additional
reolcations are generated in the purgatory.ro file:

R_AARCH64_ADR_PREL_PG_HI21
R_AARCH64_ADD_ABS_LO12_NC
R_AARCH64_LDST64_ABS_LO12_NC

This patch modifies the arm64 machine_apply_elf_rel() function to handle
these relocations.

Cc: Geoff Levand <geoff at infradead.org>
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---
 kexec/arch/arm64/kexec-arm64.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 2e8839a..e067a23 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -550,6 +550,14 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 # define R_AARCH64_ADR_PREL_LO21 274
 #endif
 
+#if !defined(R_AARCH64_ADR_PREL_PG_HI21)
+# define R_AARCH64_ADR_PREL_PG_HI21 275
+#endif
+
+#if !defined(R_AARCH64_ADD_ABS_LO12_NC)
+# define R_AARCH64_ADD_ABS_LO12_NC 277
+#endif
+
 #if !defined(R_AARCH64_JUMP26)
 # define R_AARCH64_JUMP26 282
 #endif
@@ -558,10 +566,15 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 # define R_AARCH64_CALL26 283
 #endif
 
+#if !defined(R_AARCH64_LDST64_ABS_LO12_NC)
+# define R_AARCH64_LDST64_ABS_LO12_NC 286
+#endif
+
 	uint64_t *loc64;
 	uint32_t *loc32;
 	uint64_t *location = (uint64_t *)ptr;
 	uint64_t data = *location;
+	uint64_t imm;
 	const char *type = NULL;
 
 	switch(r_type) {
@@ -585,6 +598,19 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
 			+ (((value - address) << 3) & 0xffffe0));
 		break;
+	case R_AARCH64_ADR_PREL_PG_HI21:
+		type = "ADR_PREL_PG_HI21";
+		imm = ((value & ~0xfff) - (address & ~0xfff)) >> 12;
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ ((imm & 3) << 29) + ((imm & 0x1ffffc) << (5 - 2)));
+		break;
+	case R_AARCH64_ADD_ABS_LO12_NC:
+		type = "R_AARCH64_ADD_ABS_LO12_NC";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ ((value & 0xfff) << 10));
+		break;
 	case R_AARCH64_JUMP26:
 		type = "JUMP26";
 		loc32 = ptr;
@@ -597,6 +623,15 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
 			+ (((value - address) >> 2) & 0x3ffffff));
 		break;
+	case R_AARCH64_LDST64_ABS_LO12_NC:
+		if (value & 7)
+			die("%s: ERROR Unaligned value: %lx\n", __func__,
+				value);
+		type = "R_AARCH64_LDST64_ABS_LO12_NC";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ ((value & 0xff8) << (10 - 3)));
+		break;
 	default:
 		die("%s: ERROR Unknown type: %lu\n", __func__, r_type);
 		break;
-- 
2.10.0



From geoff at infradead.org  Wed Oct 19 15:52:30 2016
From: geoff at infradead.org (Geoff Levand)
Date: Wed, 19 Oct 2016 15:52:30 -0700
Subject: [PATCH] arm64: Add support for additional relocations in the
 kexec purgatory code
In-Reply-To: <1476892714-27304-1-git-send-email-catalin.marinas@arm.com>
References: <1476892714-27304-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <15f9c4d2-34a8-fd74-05ec-0a8df41bc93a@infradead.org>

Hi Catalin,

On 10/19/2016 08:58 AM, Catalin Marinas wrote:
> diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
> index 2e8839a..e067a23 100644
> --- a/kexec/arch/arm64/kexec-arm64.c
> +++ b/kexec/arch/arm64/kexec-arm64.c
> @@ -585,6 +598,19 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
>  		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
>  			+ (((value - address) << 3) & 0xffffe0));
>  		break;
> +	case R_AARCH64_ADR_PREL_PG_HI21:
> +		type = "ADR_PREL_PG_HI21";
> +		imm = ((value & ~0xfff) - (address & ~0xfff)) >> 12;
> +		loc32 = ptr;
> +		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
> +			+ ((imm & 3) << 29) + ((imm & 0x1ffffc) << (5 - 2)));
> +		break;
> +	case R_AARCH64_ADD_ABS_LO12_NC:
> +		type = "R_AARCH64_ADD_ABS_LO12_NC";

Following with the others, this should be 'type = "ADD_ABS_LO12_NC"'.

> +		loc32 = ptr;
> +		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
> +			+ ((value & 0xfff) << 10));
> +		break;
>  	case R_AARCH64_JUMP26:
>  		type = "JUMP26";
>  		loc32 = ptr;
> @@ -597,6 +623,15 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
>  		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
>  			+ (((value - address) >> 2) & 0x3ffffff));
>  		break;
> +	case R_AARCH64_LDST64_ABS_LO12_NC:
> +		if (value & 7)
> +			die("%s: ERROR Unaligned value: %lx\n", __func__,
> +				value);
> +		type = "R_AARCH64_LDST64_ABS_LO12_NC";

And type = "LDST64_ABS_LO12_NC" here.

> +		loc32 = ptr;
> +		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
> +			+ ((value & 0xff8) << (10 - 3)));
> +		break;
>  	default:
>  		die("%s: ERROR Unknown type: %lu\n", __func__, r_type);
>  		break;

Otherwise, looks good.  Thanks for taking time to make the fix.

-Geoff 


From kings3 at absamail.co.za  Wed Oct 19 22:44:02 2016
From: kings3 at absamail.co.za (kings3 at absamail.co.za)
Date: Thu, 20 Oct 2016 07:44:02 +0200
Subject: Funding Approved In Minutes!
Message-ID: <201610200547.u9K5l66k002013-u9K5l66l002013@fortimail-01.voxtelecom.co.za>

Hello,

We currently have opennings to fund early startups at the preferential interest rate of two percent per year.

Regards,
Lionel Griffin 


From catalin.marinas at arm.com  Thu Oct 20 03:12:29 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 20 Oct 2016 11:12:29 +0100
Subject: [PATCH] arm64: Add support for additional relocations in the
 kexec purgatory code
In-Reply-To: <15f9c4d2-34a8-fd74-05ec-0a8df41bc93a@infradead.org>
References: <1476892714-27304-1-git-send-email-catalin.marinas@arm.com>
 <15f9c4d2-34a8-fd74-05ec-0a8df41bc93a@infradead.org>
Message-ID: <20161020101228.GE23600@e104818-lin.cambridge.arm.com>

On Wed, Oct 19, 2016 at 03:52:30PM -0700, Geoff Levand wrote:
> Hi Catalin,
> 
> On 10/19/2016 08:58 AM, Catalin Marinas wrote:
> > diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
> > index 2e8839a..e067a23 100644
> > --- a/kexec/arch/arm64/kexec-arm64.c
> > +++ b/kexec/arch/arm64/kexec-arm64.c
> > @@ -585,6 +598,19 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
> >  		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
> >  			+ (((value - address) << 3) & 0xffffe0));
> >  		break;
> > +	case R_AARCH64_ADR_PREL_PG_HI21:
> > +		type = "ADR_PREL_PG_HI21";
> > +		imm = ((value & ~0xfff) - (address & ~0xfff)) >> 12;
> > +		loc32 = ptr;
> > +		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
> > +			+ ((imm & 3) << 29) + ((imm & 0x1ffffc) << (5 - 2)));
> > +		break;
> > +	case R_AARCH64_ADD_ABS_LO12_NC:
> > +		type = "R_AARCH64_ADD_ABS_LO12_NC";
> 
> Following with the others, this should be 'type = "ADD_ABS_LO12_NC"'.

Ah, I missed this detail. I'll post a v2 shortly.

Thanks.

-- 
Catalin


From catalin.marinas at arm.com  Thu Oct 20 03:43:31 2016
From: catalin.marinas at arm.com (Catalin Marinas)
Date: Thu, 20 Oct 2016 11:43:31 +0100
Subject: [PATCH v2] arm64: Add support for additional relocations in the kexec
 purgatory code
Message-ID: <1476960211-25594-1-git-send-email-catalin.marinas@arm.com>

When compiling the kexec-tools with gcc6, the following additional
reolcations are generated in the purgatory.ro file:

R_AARCH64_ADR_PREL_PG_HI21
R_AARCH64_ADD_ABS_LO12_NC
R_AARCH64_LDST64_ABS_LO12_NC

This patch modifies the arm64 machine_apply_elf_rel() function to handle
these relocations.

Cc: Geoff Levand <geoff at infradead.org>
Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
---

Changes for v2:
- Fixed the type string to drop the "R_AARCH64_" prefix

 kexec/arch/arm64/kexec-arm64.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 2e8839a..e067a23 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -550,6 +550,14 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 # define R_AARCH64_ADR_PREL_LO21 274
 #endif
 
+#if !defined(R_AARCH64_ADR_PREL_PG_HI21)
+# define R_AARCH64_ADR_PREL_PG_HI21 275
+#endif
+
+#if !defined(R_AARCH64_ADD_ABS_LO12_NC)
+# define R_AARCH64_ADD_ABS_LO12_NC 277
+#endif
+
 #if !defined(R_AARCH64_JUMP26)
 # define R_AARCH64_JUMP26 282
 #endif
@@ -558,10 +566,15 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 # define R_AARCH64_CALL26 283
 #endif
 
+#if !defined(R_AARCH64_LDST64_ABS_LO12_NC)
+# define R_AARCH64_LDST64_ABS_LO12_NC 286
+#endif
+
 	uint64_t *loc64;
 	uint32_t *loc32;
 	uint64_t *location = (uint64_t *)ptr;
 	uint64_t data = *location;
+	uint64_t imm;
 	const char *type = NULL;
 
 	switch(r_type) {
@@ -585,6 +598,19 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
 			+ (((value - address) << 3) & 0xffffe0));
 		break;
+	case R_AARCH64_ADR_PREL_PG_HI21:
+		type = "ADR_PREL_PG_HI21";
+		imm = ((value & ~0xfff) - (address & ~0xfff)) >> 12;
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ ((imm & 3) << 29) + ((imm & 0x1ffffc) << (5 - 2)));
+		break;
+	case R_AARCH64_ADD_ABS_LO12_NC:
+		type = "ADD_ABS_LO12_NC";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ ((value & 0xfff) << 10));
+		break;
 	case R_AARCH64_JUMP26:
 		type = "JUMP26";
 		loc32 = ptr;
@@ -597,6 +623,15 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
 			+ (((value - address) >> 2) & 0x3ffffff));
 		break;
+	case R_AARCH64_LDST64_ABS_LO12_NC:
+		if (value & 7)
+			die("%s: ERROR Unaligned value: %lx\n", __func__,
+				value);
+		type = "LDST64_ABS_LO12_NC";
+		loc32 = ptr;
+		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
+			+ ((value & 0xff8) << (10 - 3)));
+		break;
 	default:
 		die("%s: ERROR Unknown type: %lu\n", __func__, r_type);
 		break;
-- 
2.10.0



From bhe at redhat.com  Thu Oct 20 04:37:11 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 20 Oct 2016 19:37:11 +0800
Subject: [PATCH v6 0/9] Fix kdump faults on system with amd iommu
Message-ID: <1476963440-23039-1-git-send-email-bhe@redhat.com>

This is v6 post. 

The principle of the fix is similar to intel iommu. Just defer the assignment
of device to domain to device driver init. But there's difference than
intel iommu. AMD iommu create protection domain and assign device to
domain in iommu driver init stage. So in this patchset I just allow the
assignment of device to domain in software level, but defer updating the
domain info, especially the pte_root to dev table entry to device driver
init stage.

v5: 
    bnx2 NIC can't reset itself during driver init. Post patch to reset
    it during driver init. IO_PAGE_FAULT can't be seen anymore.
    
    Below is link of v5 post.
    https://lists.linuxfoundation.org/pipermail/iommu/2016-September/018527.html

v5->v6:
    According to Joerg's comments made several below main changes:
    - Add sanity check when copy old dev tables. 

    - Discard the old patch 6/8.

    - If a device is set up with guest translations (DTE.GV=1), then don't
      copy that information but move the device over to an empty guest-cr3
      table and handle the faults in the PPR log (which just answer them
      with INVALID).

Issues need be discussed:
    - Joerg suggested hooking the behaviour that updates domain info into
      dte entry into the set_dma_mask call-back. I tried, but on my local
      machine with amd iommu v2, an ohci pci device doesn't call set_dma_mask.
      Then IO_PAGE_FAULT printing flooded.

      00:12.0 USB controller: Advanced Micro Devices, Inc. [AMD] FCH USB OHCI Controller (rev 11)

    - About GCR3 root pointer copying issue, I don't know how to setup the
      test environment and haven't tested yet. Hope Joerg or Zongshun can
      tell what steps should be taken to test it, or help take a test in your
      test environemnt.
 
Baoquan He (9):
  iommu/amd: Detect pre enabled translation
  iommu/amd: add several helper function
  iommu/amd: Define bit fields for DTE particularly
  iommu/amd: Add function copy_dev_tables
  iommu/amd: copy old trans table from old kernel
  iommu/amd: Don't update domain info to dte entry at iommu init stage
  iommu/amd: Update domain into to dte entry during device driver init
  iommu/amd: Add sanity check of irq remap information of old dev table
    entry
  iommu/amd: Don't copy GCR3 table root pointer

 drivers/iommu/amd_iommu.c       |  93 +++++++++++++-------
 drivers/iommu/amd_iommu_init.c  | 189 +++++++++++++++++++++++++++++++++++++---
 drivers/iommu/amd_iommu_proto.h |   2 +
 drivers/iommu/amd_iommu_types.h |  53 ++++++++++-
 drivers/iommu/amd_iommu_v2.c    |  18 +++-
 5 files changed, 307 insertions(+), 48 deletions(-)

-- 
2.5.5



From bhe at redhat.com  Thu Oct 20 04:37:12 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 20 Oct 2016 19:37:12 +0800
Subject: [PATCH v6 1/9] iommu/amd: Detect pre enabled translation
In-Reply-To: <1476963440-23039-1-git-send-email-bhe@redhat.com>
References: <1476963440-23039-1-git-send-email-bhe@redhat.com>
Message-ID: <1476963440-23039-2-git-send-email-bhe@redhat.com>

Add functions to check whether translation is already enabled in IOMMU.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 drivers/iommu/amd_iommu_init.c  | 25 +++++++++++++++++++++++++
 drivers/iommu/amd_iommu_proto.h |  1 +
 drivers/iommu/amd_iommu_types.h |  4 ++++
 3 files changed, 30 insertions(+)

diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 157e934..1628d7e 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -251,6 +251,26 @@ static int amd_iommu_enable_interrupts(void);
 static int __init iommu_go_to_state(enum iommu_init_state state);
 static void init_device_table_dma(void);
 
+
+bool translation_pre_enabled(struct amd_iommu *iommu)
+{
+	return (iommu->flags & AMD_IOMMU_FLAG_TRANS_PRE_ENABLED);
+}
+
+static void clear_translation_pre_enabled(struct amd_iommu *iommu)
+{
+	iommu->flags &= ~AMD_IOMMU_FLAG_TRANS_PRE_ENABLED;
+}
+
+static void init_translation_status(struct amd_iommu *iommu)
+{
+	u32 ctrl;
+
+	ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
+	if (ctrl & (1<<CONTROL_IOMMU_EN))
+		iommu->flags |= AMD_IOMMU_FLAG_TRANS_PRE_ENABLED;
+}
+
 static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu,
 				    u8 bank, u8 cntr, u8 fxn,
 				    u64 *value, bool is_write);
@@ -1389,6 +1409,11 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
 
 	iommu->int_enabled = false;
 
+	init_translation_status(iommu);
+
+	if (translation_pre_enabled(iommu))
+		pr_warn("Translation is already enabled - trying to copy translation structures\n");
+
 	ret = init_iommu_from_acpi(iommu, h);
 	if (ret)
 		return ret;
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h
index 7eb60c1..9560183 100644
--- a/drivers/iommu/amd_iommu_proto.h
+++ b/drivers/iommu/amd_iommu_proto.h
@@ -93,4 +93,5 @@ static inline bool iommu_feature(struct amd_iommu *iommu, u64 f)
 	return !!(iommu->features & f);
 }
 
+extern bool translation_pre_enabled(struct amd_iommu *iommu);
 #endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 0d91785..2bbc19d 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -416,6 +416,7 @@ extern struct kmem_cache *amd_iommu_irq_cache;
 #define APERTURE_PAGE_INDEX(a)	(((a) >> 21) & 0x3fULL)
 
 
+
 /*
  * This struct is used to pass information about
  * incoming PPR faults around.
@@ -434,6 +435,8 @@ struct iommu_domain;
 struct irq_domain;
 struct amd_irte_ops;
 
+#define AMD_IOMMU_FLAG_TRANS_PRE_ENABLED      (1 << 0)
+
 /*
  * This structure contains generic data for  IOMMU protection domains
  * independent of their use.
@@ -566,6 +569,7 @@ struct amd_iommu {
 	struct amd_irte_ops *irte_ops;
 #endif
 
+	u32 flags;
 	volatile u64 __aligned(8) cmd_sem;
 };
 
-- 
2.5.5



From bhe at redhat.com  Thu Oct 20 04:37:13 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 20 Oct 2016 19:37:13 +0800
Subject: [PATCH v6 2/9] iommu/amd: add several helper function
In-Reply-To: <1476963440-23039-1-git-send-email-bhe@redhat.com>
References: <1476963440-23039-1-git-send-email-bhe@redhat.com>
Message-ID: <1476963440-23039-3-git-send-email-bhe@redhat.com>

Move per iommu enabling code into a wrapper function early_enable_iommu().
This can make later kdump change easier.

And also add iommu_disable_command_buffer and iommu_disable_event_buffer
for later usage.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 drivers/iommu/amd_iommu_init.c | 42 +++++++++++++++++++++++++++++++-----------
 1 file changed, 31 insertions(+), 11 deletions(-)

diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 1628d7e..67f1457 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -625,6 +625,14 @@ static void iommu_enable_command_buffer(struct amd_iommu *iommu)
 	amd_iommu_reset_cmd_buffer(iommu);
 }
 
+/*
+ * This function disables the command buffer
+ */
+static void iommu_disable_command_buffer(struct amd_iommu *iommu)
+{
+	iommu_feature_disable(iommu, CONTROL_CMDBUF_EN);
+}
+
 static void __init free_command_buffer(struct amd_iommu *iommu)
 {
 	free_pages((unsigned long)iommu->cmd_buf, get_order(CMD_BUFFER_SIZE));
@@ -657,6 +665,14 @@ static void iommu_enable_event_buffer(struct amd_iommu *iommu)
 	iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
 }
 
+/*
+ * This function disables the command buffer
+ */
+static void iommu_disable_event_buffer(struct amd_iommu *iommu)
+{
+	iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN);
+}
+
 static void __init free_event_buffer(struct amd_iommu *iommu)
 {
 	free_pages((unsigned long)iommu->evt_buf, get_order(EVT_BUFFER_SIZE));
@@ -2026,6 +2042,19 @@ static void iommu_enable_ga(struct amd_iommu *iommu)
 #endif
 }
 
+static void early_enable_iommu(struct amd_iommu *iommu)
+{
+	iommu_disable(iommu);
+	iommu_init_flags(iommu);
+	iommu_set_device_table(iommu);
+	iommu_enable_command_buffer(iommu);
+	iommu_enable_event_buffer(iommu);
+	iommu_set_exclusion_range(iommu);
+	iommu_enable_ga(iommu);
+	iommu_enable(iommu);
+	iommu_flush_all_caches(iommu);
+}
+
 /*
  * This function finally enables all IOMMUs found in the system after
  * they have been initialized
@@ -2034,17 +2063,8 @@ static void early_enable_iommus(void)
 {
 	struct amd_iommu *iommu;
 
-	for_each_iommu(iommu) {
-		iommu_disable(iommu);
-		iommu_init_flags(iommu);
-		iommu_set_device_table(iommu);
-		iommu_enable_command_buffer(iommu);
-		iommu_enable_event_buffer(iommu);
-		iommu_set_exclusion_range(iommu);
-		iommu_enable_ga(iommu);
-		iommu_enable(iommu);
-		iommu_flush_all_caches(iommu);
-	}
+	for_each_iommu(iommu)
+		early_enable_iommu(iommu);
 
 #ifdef CONFIG_IRQ_REMAP
 	if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
-- 
2.5.5



From bhe at redhat.com  Thu Oct 20 04:37:14 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 20 Oct 2016 19:37:14 +0800
Subject: [PATCH v6 3/9] iommu/amd: Define bit fields for DTE particularly
In-Reply-To: <1476963440-23039-1-git-send-email-bhe@redhat.com>
References: <1476963440-23039-1-git-send-email-bhe@redhat.com>
Message-ID: <1476963440-23039-4-git-send-email-bhe@redhat.com>

In amd-vi spec several bits of IO PTE fields and DTE fields are similar
so that both of them can share the same MACRO definition. However
defining their respecitve bit fields can make code more read-able. So
do it in this patch.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 drivers/iommu/amd_iommu.c       |  8 ++++----
 drivers/iommu/amd_iommu_types.h | 18 ++++++++++++++----
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 754595e..0b0e50e 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1476,9 +1476,9 @@ static int iommu_map_page(struct protection_domain *dom,
 
 	if (count > 1) {
 		__pte = PAGE_SIZE_PTE(phys_addr, page_size);
-		__pte |= PM_LEVEL_ENC(7) | IOMMU_PTE_P | IOMMU_PTE_FC;
+		__pte |= PM_LEVEL_ENC(7) | IOMMU_PTE_PR | IOMMU_PTE_FC;
 	} else
-		__pte = phys_addr | IOMMU_PTE_P | IOMMU_PTE_FC;
+		__pte = phys_addr | IOMMU_PTE_PR | IOMMU_PTE_FC;
 
 	if (prot & IOMMU_PROT_IR)
 		__pte |= IOMMU_PTE_IR;
@@ -1805,7 +1805,7 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
 
 	pte_root |= (domain->mode & DEV_ENTRY_MODE_MASK)
 		    << DEV_ENTRY_MODE_SHIFT;
-	pte_root |= IOMMU_PTE_IR | IOMMU_PTE_IW | IOMMU_PTE_P | IOMMU_PTE_TV;
+	pte_root |= DTE_FLAG_IR | DTE_FLAG_IW | DTE_FLAG_V | DTE_FLAG_TV;
 
 	flags = amd_iommu_dev_table[devid].data[1];
 
@@ -1848,7 +1848,7 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
 static void clear_dte_entry(u16 devid)
 {
 	/* remove entry from the device table seen by the hardware */
-	amd_iommu_dev_table[devid].data[0]  = IOMMU_PTE_P | IOMMU_PTE_TV;
+	amd_iommu_dev_table[devid].data[0]  = DTE_FLAG_V | DTE_FLAG_TV;
 	amd_iommu_dev_table[devid].data[1] &= DTE_FLAG_MASK;
 
 	amd_iommu_apply_erratum_63(devid);
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 2bbc19d..6a4378f 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -265,7 +265,7 @@
 #define PM_LEVEL_INDEX(x, a)	(((a) >> PM_LEVEL_SHIFT((x))) & 0x1ffULL)
 #define PM_LEVEL_ENC(x)		(((x) << 9) & 0xe00ULL)
 #define PM_LEVEL_PDE(x, a)	((a) | PM_LEVEL_ENC((x)) | \
-				 IOMMU_PTE_P | IOMMU_PTE_IR | IOMMU_PTE_IW)
+				 IOMMU_PTE_PR | IOMMU_PTE_IR | IOMMU_PTE_IW)
 #define PM_PTE_LEVEL(pte)	(((pte) >> 9) & 0x7ULL)
 
 #define PM_MAP_4k		0
@@ -314,13 +314,23 @@
 #define PTE_LEVEL_PAGE_SIZE(level)			\
 	(1ULL << (12 + (9 * (level))))
 
-#define IOMMU_PTE_P  (1ULL << 0)
-#define IOMMU_PTE_TV (1ULL << 1)
+/*
+ * Bit value definition for I/O PTE fields
+ */
+#define IOMMU_PTE_PR (1ULL << 0)
 #define IOMMU_PTE_U  (1ULL << 59)
 #define IOMMU_PTE_FC (1ULL << 60)
 #define IOMMU_PTE_IR (1ULL << 61)
 #define IOMMU_PTE_IW (1ULL << 62)
 
+/*
+ * Bit value definition for DTE fields
+ */
+#define DTE_FLAG_V  (1ULL << 0)
+#define DTE_FLAG_TV (1ULL << 1)
+#define DTE_FLAG_IR (1ULL << 61)
+#define DTE_FLAG_IW (1ULL << 62)
+
 #define DTE_FLAG_IOTLB	(1ULL << 32)
 #define DTE_FLAG_GV	(1ULL << 55)
 #define DTE_FLAG_MASK	(0x3ffULL << 32)
@@ -342,7 +352,7 @@
 #define GCR3_VALID		0x01ULL
 
 #define IOMMU_PAGE_MASK (((1ULL << 52) - 1) & ~0xfffULL)
-#define IOMMU_PTE_PRESENT(pte) ((pte) & IOMMU_PTE_P)
+#define IOMMU_PTE_PRESENT(pte) ((pte) & IOMMU_PTE_PR)
 #define IOMMU_PTE_PAGE(pte) (phys_to_virt((pte) & IOMMU_PAGE_MASK))
 #define IOMMU_PTE_MODE(pte) (((pte) >> 9) & 0x07)
 
-- 
2.5.5



From bhe at redhat.com  Thu Oct 20 04:37:15 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 20 Oct 2016 19:37:15 +0800
Subject: [PATCH v6 4/9] iommu/amd: Add function copy_dev_tables
In-Reply-To: <1476963440-23039-1-git-send-email-bhe@redhat.com>
References: <1476963440-23039-1-git-send-email-bhe@redhat.com>
Message-ID: <1476963440-23039-5-git-send-email-bhe@redhat.com>

Add function copy_dev_tables to copy the old DEV table entries of the panicked
kernel to the new allocated DEV table. Since all iommus share the same DTE table
the copy only need be done once as long as the physical address of old DEV table
is retrieved from iommu reg. Besides, we also need to:

  - Check whether all IOMMUs actually use the same device table with the same size

  - Verify that the size of the old device table is the expected size.

  - Reserve the old domain id occupied in 1st kernel to avoid touching the old
    io-page tables. Then on-flight DMA can continue looking it up.

And define MACRO DEV_DOMID_MASK to replace magic number 0xffffULL because
it need be reused in copy_dev_tables.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 drivers/iommu/amd_iommu.c       |  2 +-
 drivers/iommu/amd_iommu_init.c  | 55 +++++++++++++++++++++++++++++++++++++++++
 drivers/iommu/amd_iommu_types.h |  1 +
 3 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 0b0e50e..d5aef72 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1838,7 +1838,7 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
 		flags    |= tmp;
 	}
 
-	flags &= ~(0xffffUL);
+	flags &= ~DEV_DOMID_MASK;
 	flags |= domain->id;
 
 	amd_iommu_dev_table[devid].data[1]  = flags;
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 67f1457..d4200e8 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -834,6 +834,61 @@ static int get_dev_entry_bit(u16 devid, u8 bit)
 }
 
 
+static int copy_dev_tables(void)
+{
+	struct dev_table_entry *old_devtb = NULL;
+	u32 lo, hi, devid, old_devtb_size;
+	phys_addr_t old_devtb_phys;
+	u64 entry, last_entry = 0;
+	struct amd_iommu *iommu;
+	u16 dom_id, dte_v;
+	static int copied;
+
+	for_each_iommu(iommu) {
+		if (!translation_pre_enabled(iommu)) {
+			pr_err("IOMMU:%d is not pre-enabled!/n",
+				iommu->index);
+			return -1;
+		}
+
+		/* All IOMMUs should use the same device table with the same size */
+		lo = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET);
+		hi = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET + 4);
+		entry = (((u64) hi) << 32) + lo;
+		if (last_entry && last_entry != entry) {
+			pr_err("IOMMU:%d should use the same dev table as others!/n",
+				iommu->index);
+			return -1;
+		}
+		last_entry = entry;
+
+		old_devtb_size = ((entry & ~PAGE_MASK) + 1) << 12;
+		if (old_devtb_size != dev_table_size) {
+			pr_err("The device table size of IOMMU:%d is not expected!/n",
+				iommu->index);
+			return -1;
+		}
+
+		old_devtb_phys = entry & PAGE_MASK;
+		old_devtb = memremap(old_devtb_phys, dev_table_size, MEMREMAP_WB);
+		if (!old_devtb)
+			return -1;
+
+		if (copied)
+			continue;
+		for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) {
+			amd_iommu_dev_table[devid] = old_devtb[devid];
+			dom_id = old_devtb[devid].data[1] & DEV_DOMID_MASK;
+			dte_v = old_devtb[devid].data[0] & DTE_FLAG_V;
+			if (dte_v && dom_id)
+				__set_bit(dom_id, amd_iommu_pd_alloc_bitmap);
+		}
+		memunmap(old_devtb);
+		copied = 1;
+	}
+	return 0;
+}
+
 void amd_iommu_apply_erratum_63(u16 devid)
 {
 	int sysmgt;
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 6a4378f..454f3bf 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -336,6 +336,7 @@
 #define DTE_FLAG_MASK	(0x3ffULL << 32)
 #define DTE_GLX_SHIFT	(56)
 #define DTE_GLX_MASK	(3)
+#define DEV_DOMID_MASK 	0xffffULL
 
 #define DTE_GCR3_VAL_A(x)	(((x) >> 12) & 0x00007ULL)
 #define DTE_GCR3_VAL_B(x)	(((x) >> 15) & 0x0ffffULL)
-- 
2.5.5



From bhe at redhat.com  Thu Oct 20 04:37:16 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 20 Oct 2016 19:37:16 +0800
Subject: [PATCH v6 5/9] iommu/amd: copy old trans table from old kernel
In-Reply-To: <1476963440-23039-1-git-send-email-bhe@redhat.com>
References: <1476963440-23039-1-git-send-email-bhe@redhat.com>
Message-ID: <1476963440-23039-6-git-send-email-bhe@redhat.com>

Here several things need be done:
- If iommu is pre-enabled in a normal kernel, just disable it and print
  warning.

- If failed to copy dev table of old kernel, continue to proceed as
  it does in normal kernel.

- Disable and Re-enable event/cmd buffer,  and install the copied DTE table
  to reg.

- Flush all caches

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 drivers/iommu/amd_iommu_init.c | 51 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 44 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index d4200e8..bc214fa 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -36,6 +36,7 @@
 #include <asm/io_apic.h>
 #include <asm/irq_remapping.h>
 
+#include <linux/crash_dump.h>
 #include "amd_iommu_proto.h"
 #include "amd_iommu_types.h"
 #include "irq_remapping.h"
@@ -1481,9 +1482,12 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
 	iommu->int_enabled = false;
 
 	init_translation_status(iommu);
-
-	if (translation_pre_enabled(iommu))
-		pr_warn("Translation is already enabled - trying to copy translation structures\n");
+	if (translation_pre_enabled(iommu) && !is_kdump_kernel()) {
+		iommu_disable(iommu);
+		clear_translation_pre_enabled(iommu);
+		pr_warn("Translation was enabled for IOMMU:%d but we are not in kdump mode\n",
+			iommu->index);
+	}
 
 	ret = init_iommu_from_acpi(iommu, h);
 	if (ret)
@@ -1975,8 +1979,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table)
 }
 
 /*
- * Init the device table to not allow DMA access for devices and
- * suppress all page faults
+ * Init the device table to not allow DMA access for devices
  */
 static void init_device_table_dma(void)
 {
@@ -2117,9 +2120,43 @@ static void early_enable_iommu(struct amd_iommu *iommu)
 static void early_enable_iommus(void)
 {
 	struct amd_iommu *iommu;
+	bool is_pre_enabled = false;
 
-	for_each_iommu(iommu)
-		early_enable_iommu(iommu);
+	for_each_iommu(iommu) {
+		if (translation_pre_enabled(iommu)) {
+			is_pre_enabled = true;
+			break;
+		}
+	}
+
+	if (!is_pre_enabled) {
+		for_each_iommu(iommu)
+			early_enable_iommu(iommu);
+	} else {
+		pr_warn("Translation is already enabled - trying to copy translation structures\n");
+		if (copy_dev_tables()) {
+			pr_err("Failed to copy DEV table from previous kernel.\n");
+			/*
+			 * If failed to copy dev tables from old kernel, continue to proceed
+			 * as it does in normal kernel.
+			 */
+			for_each_iommu(iommu) {
+				clear_translation_pre_enabled(iommu);
+				early_enable_iommu(iommu);
+			}
+		} else {
+			pr_info("Copied DEV table from previous kernel.\n");
+			for_each_iommu(iommu) {
+				iommu_disable_command_buffer(iommu);
+				iommu_disable_event_buffer(iommu);
+				iommu_enable_command_buffer(iommu);
+				iommu_enable_event_buffer(iommu);
+				iommu_enable_ga(iommu);
+				iommu_set_device_table(iommu);
+				iommu_flush_all_caches(iommu);
+			}
+		}
+	}
 
 #ifdef CONFIG_IRQ_REMAP
 	if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
-- 
2.5.5



From bhe at redhat.com  Thu Oct 20 04:37:17 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 20 Oct 2016 19:37:17 +0800
Subject: [PATCH v6 6/9] iommu/amd: Don't update domain info to dte entry at
 iommu init stage
In-Reply-To: <1476963440-23039-1-git-send-email-bhe@redhat.com>
References: <1476963440-23039-1-git-send-email-bhe@redhat.com>
Message-ID: <1476963440-23039-7-git-send-email-bhe@redhat.com>

AMD iommu creates protection domain and assign each device to it during
iommu driver initialization stage. This happened just after system pci
bus scanning stage, and much earlier than device driver init stage. So
at this time if in kdump kernel the domain info, especially pte_root,
can't be updated to dte entry. We should wait until device driver init
stage.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 drivers/iommu/amd_iommu.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index d5aef72..aa78506 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -138,6 +138,7 @@ struct iommu_dev_data {
 					     PPR completions */
 	u32 errata;			  /* Bitmap for errata to apply */
 	bool use_vapic;			  /* Enable device to use vapic mode */
+	bool domain_updated;
 };
 
 /*
@@ -1799,6 +1800,15 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
 {
 	u64 pte_root = 0;
 	u64 flags = 0;
+	struct iommu_dev_data *dev_data;
+	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+	dev_data = find_dev_data(devid);
+	if (!dev_data)
+		return;
+
+	if (translation_pre_enabled(iommu) && !dev_data->domain_updated)
+		return;
 
 	if (domain->mode != PAGE_MODE_NONE)
 		pte_root = virt_to_phys(domain->pt_root);
@@ -1847,6 +1857,14 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
 
 static void clear_dte_entry(u16 devid)
 {
+	struct iommu_dev_data *dev_data;
+	struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+	dev_data = find_dev_data(devid);
+	if (!dev_data)
+		return;
+	if (translation_pre_enabled(iommu) && !dev_data->domain_updated)
+		return;
 	/* remove entry from the device table seen by the hardware */
 	amd_iommu_dev_table[devid].data[0]  = DTE_FLAG_V | DTE_FLAG_TV;
 	amd_iommu_dev_table[devid].data[1] &= DTE_FLAG_MASK;
-- 
2.5.5



From bhe at redhat.com  Thu Oct 20 04:37:18 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 20 Oct 2016 19:37:18 +0800
Subject: [PATCH v6 7/9] iommu/amd: Update domain into to dte entry during
 device driver init
In-Reply-To: <1476963440-23039-1-git-send-email-bhe@redhat.com>
References: <1476963440-23039-1-git-send-email-bhe@redhat.com>
Message-ID: <1476963440-23039-8-git-send-email-bhe@redhat.com>

All devices are supposed to reset themselves at device driver initialization
stage. At this time if in kdump kernel those on-flight DMA will be stopped
because of device reset. It's best time to update the protection domain info,
especially pte_root, to dte entry which the device relates to.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 drivers/iommu/amd_iommu.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index aa78506..3b95904 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2396,6 +2396,10 @@ static dma_addr_t __map_single(struct device *dev,
 			       enum dma_data_direction direction,
 			       u64 dma_mask)
 {
+	struct iommu_dev_data *dev_data = get_dev_data(dev);
+	struct amd_iommu *iommu = amd_iommu_rlookup_table[dev_data->devid];
+	struct protection_domain *domain = get_domain(dev);
+	u16 alias = amd_iommu_alias_table[dev_data->devid];
 	dma_addr_t offset = paddr & ~PAGE_MASK;
 	dma_addr_t address, start, ret;
 	unsigned int pages;
@@ -2410,6 +2414,13 @@ static dma_addr_t __map_single(struct device *dev,
 		goto out;
 
 	prot = dir2prot(direction);
+	if (translation_pre_enabled(iommu) && !dev_data->domain_updated) {
+		dev_data->domain_updated = true;
+		set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled);
+		if (alias != dev_data->devid)
+			set_dte_entry(alias, domain, dev_data->ats.enabled);
+		device_flush_dte(dev_data);
+	}
 
 	start = address;
 	for (i = 0; i < pages; ++i) {
@@ -2555,6 +2566,9 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 		  int nelems, enum dma_data_direction direction,
 		  unsigned long attrs)
 {
+	struct iommu_dev_data *dev_data = get_dev_data(dev);
+	struct amd_iommu *iommu = amd_iommu_rlookup_table[dev_data->devid];
+	u16 alias = amd_iommu_alias_table[dev_data->devid];
 	int mapped_pages = 0, npages = 0, prot = 0, i;
 	struct protection_domain *domain;
 	struct dma_ops_domain *dma_dom;
@@ -2576,6 +2590,13 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 		goto out_err;
 
 	prot = dir2prot(direction);
+	if (translation_pre_enabled(iommu) && !dev_data->domain_updated) {
+		dev_data->domain_updated = true;
+		set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled);
+		if (alias != dev_data->devid)
+			set_dte_entry(alias, domain, dev_data->ats.enabled);
+		device_flush_dte(dev_data);
+	}
 
 	/* Map all sg entries */
 	for_each_sg(sglist, s, nelems, i) {
-- 
2.5.5



From bhe at redhat.com  Thu Oct 20 04:37:19 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 20 Oct 2016 19:37:19 +0800
Subject: [PATCH v6 8/9] iommu/amd: Add sanity check of irq remap information
 of old dev table entry
In-Reply-To: <1476963440-23039-1-git-send-email-bhe@redhat.com>
References: <1476963440-23039-1-git-send-email-bhe@redhat.com>
Message-ID: <1476963440-23039-9-git-send-email-bhe@redhat.com>

Firstly split the dev table entry copy into address translation part and
irq remapping part. Because these two parts could be configured to
be available indepentently.

Secondly check if IntCtl and IntTabLen are 10b and 1000b if they are
set.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 drivers/iommu/amd_iommu.c       |  5 -----
 drivers/iommu/amd_iommu_init.c  | 25 ++++++++++++++++++++++---
 drivers/iommu/amd_iommu_types.h |  8 ++++++++
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 3b95904..46f438f 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3658,11 +3658,6 @@ EXPORT_SYMBOL(amd_iommu_device_info);
 
 static struct irq_chip amd_ir_chip;
 
-#define DTE_IRQ_PHYS_ADDR_MASK	(((1ULL << 45)-1) << 6)
-#define DTE_IRQ_REMAP_INTCTL    (2ULL << 60)
-#define DTE_IRQ_TABLE_LEN       (8ULL << 1)
-#define DTE_IRQ_REMAP_ENABLE    1ULL
-
 static void set_dte_irq_entry(u16 devid, struct irq_remap_table *table)
 {
 	u64 dte;
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index bc214fa..d936c40 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -837,12 +837,12 @@ static int get_dev_entry_bit(u16 devid, u8 bit)
 
 static int copy_dev_tables(void)
 {
+	u64 int_ctl, int_tab_len, entry, last_entry = 0;
 	struct dev_table_entry *old_devtb = NULL;
 	u32 lo, hi, devid, old_devtb_size;
 	phys_addr_t old_devtb_phys;
-	u64 entry, last_entry = 0;
 	struct amd_iommu *iommu;
-	u16 dom_id, dte_v;
+	u16 dom_id, dte_v, irq_v;
 	static int copied;
 
 	for_each_iommu(iommu) {
@@ -881,8 +881,27 @@ static int copy_dev_tables(void)
 			amd_iommu_dev_table[devid] = old_devtb[devid];
 			dom_id = old_devtb[devid].data[1] & DEV_DOMID_MASK;
 			dte_v = old_devtb[devid].data[0] & DTE_FLAG_V;
-			if (dte_v && dom_id)
+			if (dte_v && dom_id) {
+				amd_iommu_dev_table[devid].data[0]
+					= old_devtb[devid].data[0];
+				amd_iommu_dev_table[devid].data[1]
+					= old_devtb[devid].data[1];
 				__set_bit(dom_id, amd_iommu_pd_alloc_bitmap);
+			}
+
+			irq_v = old_devtb[devid].data[2] & DTE_IRQ_REMAP_ENABLE;
+			int_ctl = old_devtb[devid].data[2] & DTE_IRQ_REMAP_INTCTL_MASK;
+			int_tab_len = old_devtb[devid].data[2] & DTE_IRQ_TABLE_LEN_MASK;
+			if (irq_v && (int_ctl || int_tab_len)) {
+				if ((int_ctl != DTE_IRQ_REMAP_INTCTL) ||
+					 (int_tab_len != DTE_IRQ_TABLE_LEN)) {
+					pr_err("Wrong old irq remapping flag: %#x\n", devid);
+					return -1;
+				}
+
+				amd_iommu_dev_table[devid].data[2]
+					= old_devtb[devid].data[2];
+			}
 		}
 		memunmap(old_devtb);
 		copied = 1;
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 454f3bf..e385d50 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -250,6 +250,14 @@
 
 #define GA_GUEST_NR		0x1
 
+/* Bit value definition for dte irq remapping fields*/
+#define DTE_IRQ_PHYS_ADDR_MASK	(((1ULL << 45)-1) << 6)
+#define DTE_IRQ_REMAP_INTCTL_MASK	(0x3ULL << 60)
+#define DTE_IRQ_TABLE_LEN_MASK	(0xfULL << 1)
+#define DTE_IRQ_REMAP_INTCTL    (2ULL << 60)
+#define DTE_IRQ_TABLE_LEN       (8ULL << 1)
+#define DTE_IRQ_REMAP_ENABLE    1ULL
+
 #define PAGE_MODE_NONE    0x00
 #define PAGE_MODE_1_LEVEL 0x01
 #define PAGE_MODE_2_LEVEL 0x02
-- 
2.5.5



From bhe at redhat.com  Thu Oct 20 04:37:20 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 20 Oct 2016 19:37:20 +0800
Subject: [PATCH v6 9/9] iommu/amd: Don't copy GCR3 table root pointer
In-Reply-To: <1476963440-23039-1-git-send-email-bhe@redhat.com>
References: <1476963440-23039-1-git-send-email-bhe@redhat.com>
Message-ID: <1476963440-23039-10-git-send-email-bhe@redhat.com>

If a device is set up with guest translations (DTE.GV=1), then don't
copy GCR3 table root pointer but move the device over to an empty
guest-cr3 table and handle the faults in the PPR log (which answer them
with INVALID). After all these PPR faults are recoverable for the device
and we should not allow the device to change old-kernels data when we
don't have to.

And clear the old GV flag when update domain information into dte entry
if the domain doesn't support IOMMUv2.

Signed-off-by: Baoquan He <bhe at redhat.com>
---
 drivers/iommu/amd_iommu.c       | 45 ++++++++++++++++++-----------------------
 drivers/iommu/amd_iommu_init.c  | 11 ++++++++++
 drivers/iommu/amd_iommu_proto.h |  1 +
 drivers/iommu/amd_iommu_types.h | 22 ++++++++++++++++++++
 drivers/iommu/amd_iommu_v2.c    | 18 ++++++++++++++++-
 5 files changed, 71 insertions(+), 26 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 46f438f..af0b9ce 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -120,28 +120,6 @@ int amd_iommu_max_glx_val = -1;
 static struct dma_map_ops amd_iommu_dma_ops;
 
 /*
- * This struct contains device specific data for the IOMMU
- */
-struct iommu_dev_data {
-	struct list_head list;		  /* For domain->dev_list */
-	struct list_head dev_data_list;	  /* For global dev_data_list */
-	struct protection_domain *domain; /* Domain the device is bound to */
-	u16 devid;			  /* PCI Device ID */
-	u16 alias;			  /* Alias Device ID */
-	bool iommu_v2;			  /* Device can make use of IOMMUv2 */
-	bool passthrough;		  /* Device is identity mapped */
-	struct {
-		bool enabled;
-		int qdep;
-	} ats;				  /* ATS state */
-	bool pri_tlp;			  /* PASID TLB required for
-					     PPR completions */
-	u32 errata;			  /* Bitmap for errata to apply */
-	bool use_vapic;			  /* Enable device to use vapic mode */
-	bool domain_updated;
-};
-
-/*
  * general struct to manage commands send to an IOMMU
  */
 struct iommu_cmd {
@@ -350,10 +328,11 @@ static struct iommu_dev_data *find_dev_data(u16 devid)
 	return dev_data;
 }
 
-static struct iommu_dev_data *get_dev_data(struct device *dev)
+struct iommu_dev_data *get_dev_data(struct device *dev)
 {
 	return dev->archdata.iommu;
 }
+EXPORT_SYMBOL(get_dev_data);
 
 /*
 * Find or create an IOMMU group for a acpihid device.
@@ -2383,6 +2362,12 @@ static int dir2prot(enum dma_data_direction direction)
 	else
 		return 0;
 }
+
+static void clear_dte_flag_gv(u16 devid)
+{
+	amd_iommu_dev_table[devid].data[0] &= (~DTE_FLAG_GV);
+}
+
 /*
  * This function contains common code for mapping of a physically
  * contiguous memory region into DMA address space. It is used by all
@@ -2417,8 +2402,13 @@ static dma_addr_t __map_single(struct device *dev,
 	if (translation_pre_enabled(iommu) && !dev_data->domain_updated) {
 		dev_data->domain_updated = true;
 		set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled);
-		if (alias != dev_data->devid)
+		if (!(domain->flags & PD_IOMMUV2_MASK))
+			clear_dte_flag_gv(dev_data->devid);
+		if (alias != dev_data->devid) {
 			set_dte_entry(alias, domain, dev_data->ats.enabled);
+			if (!(domain->flags & PD_IOMMUV2_MASK))
+				clear_dte_flag_gv(alias);
+		}
 		device_flush_dte(dev_data);
 	}
 
@@ -2593,8 +2583,13 @@ static int map_sg(struct device *dev, struct scatterlist *sglist,
 	if (translation_pre_enabled(iommu) && !dev_data->domain_updated) {
 		dev_data->domain_updated = true;
 		set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled);
-		if (alias != dev_data->devid)
+		if (!(domain->flags & PD_IOMMUV2_MASK))
+			clear_dte_flag_gv(dev_data->devid);
+		if (alias != dev_data->devid) {
 			set_dte_entry(alias, domain, dev_data->ats.enabled);
+			if (!(domain->flags & PD_IOMMUV2_MASK))
+				clear_dte_flag_gv(alias);
+		}
 		device_flush_dte(dev_data);
 	}
 
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index d936c40..9ddce11 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -204,6 +204,7 @@ u16 *amd_iommu_alias_table;
  * for a specific device. It is also indexed by the PCI device id.
  */
 struct amd_iommu **amd_iommu_rlookup_table;
+EXPORT_SYMBOL(amd_iommu_rlookup_table);
 
 /*
  * This table is used to find the irq remapping table for a given device id
@@ -257,6 +258,7 @@ bool translation_pre_enabled(struct amd_iommu *iommu)
 {
 	return (iommu->flags & AMD_IOMMU_FLAG_TRANS_PRE_ENABLED);
 }
+EXPORT_SYMBOL(translation_pre_enabled);
 
 static void clear_translation_pre_enabled(struct amd_iommu *iommu)
 {
@@ -844,6 +846,7 @@ static int copy_dev_tables(void)
 	struct amd_iommu *iommu;
 	u16 dom_id, dte_v, irq_v;
 	static int copied;
+	u64 tmp;
 
 	for_each_iommu(iommu) {
 		if (!translation_pre_enabled(iommu)) {
@@ -887,6 +890,14 @@ static int copy_dev_tables(void)
 				amd_iommu_dev_table[devid].data[1]
 					= old_devtb[devid].data[1];
 				__set_bit(dom_id, amd_iommu_pd_alloc_bitmap);
+				/* If gcr3 table existed, mask it out */
+				if (old_devtb[devid].data[0] & DTE_FLAG_GV) {
+					tmp = DTE_GCR3_VAL_B(~0ULL) << DTE_GCR3_SHIFT_B;
+					tmp |= DTE_GCR3_VAL_C(~0ULL) << DTE_GCR3_SHIFT_C;
+					amd_iommu_dev_table[devid].data[1] &= ~tmp;
+					tmp = DTE_GCR3_VAL_A(~0ULL) << DTE_GCR3_SHIFT_A;
+					amd_iommu_dev_table[devid].data[0] &= ~tmp;
+				}
 			}
 
 			irq_v = old_devtb[devid].data[2] & DTE_IRQ_REMAP_ENABLE;
diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h
index 9560183..d6a2c36 100644
--- a/drivers/iommu/amd_iommu_proto.h
+++ b/drivers/iommu/amd_iommu_proto.h
@@ -94,4 +94,5 @@ static inline bool iommu_feature(struct amd_iommu *iommu, u64 f)
 }
 
 extern bool translation_pre_enabled(struct amd_iommu *iommu);
+extern struct iommu_dev_data *get_dev_data(struct device *dev);
 #endif /* _ASM_X86_AMD_IOMMU_PROTO_H  */
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index e385d50..1d316cd 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -612,6 +612,28 @@ struct devid_map {
 	bool cmd_line;
 };
 
+/*
+ * This struct contains device specific data for the IOMMU
+ */
+struct iommu_dev_data {
+	struct list_head list;		  /* For domain->dev_list */
+	struct list_head dev_data_list;	  /* For global dev_data_list */
+	struct protection_domain *domain; /* Domain the device is bound to */
+	u16 devid;			  /* PCI Device ID */
+	u16 alias;			  /* Alias Device ID */
+	bool iommu_v2;			  /* Device can make use of IOMMUv2 */
+	bool passthrough;		  /* Device is identity mapped */
+	struct {
+		bool enabled;
+		int qdep;
+	} ats;				  /* ATS state */
+	bool pri_tlp;			  /* PASID TLB required for
+					     PPR completions */
+	u32 errata;			  /* Bitmap for errata to apply */
+	bool use_vapic;			  /* Enable device to use vapic mode */
+	bool domain_updated;
+};
+
 /* Map HPET and IOAPIC ids to the devid used by the IOMMU */
 extern struct list_head ioapic_map;
 extern struct list_head hpet_map;
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index 594849a..7c4a847 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -561,13 +561,29 @@ static int ppr_notifier(struct notifier_block *nb, unsigned long e, void *data)
 	unsigned long flags;
 	struct fault *fault;
 	bool finish;
-	u16 tag;
+	u16 tag, devid;
 	int ret;
+	struct iommu_dev_data *dev_data;
+	struct pci_dev *pdev = NULL;
 
 	iommu_fault = data;
 	tag         = iommu_fault->tag & 0x1ff;
 	finish      = (iommu_fault->tag >> 9) & 1;
 
+	devid = iommu_fault->device_id;
+	pdev = pci_get_bus_and_slot(PCI_BUS_NUM(devid), devid & 0xff);
+	if (!pdev)
+		return -ENODEV;
+	dev_data = get_dev_data(&pdev->dev);
+
+	/* In kdump kernel pci dev is not initialized yet -> send INVALID */
+	if (translation_pre_enabled(amd_iommu_rlookup_table[devid])
+		&& !dev_data->domain_updated) {
+		amd_iommu_complete_ppr(pdev, iommu_fault->pasid,
+				       PPR_INVALID, tag);
+		goto out;
+	}
+
 	ret = NOTIFY_DONE;
 	dev_state = get_device_state(iommu_fault->device_id);
 	if (dev_state == NULL)
-- 
2.5.5



From vicgeneral at iglesiadeasturias.org  Thu Oct 20 07:10:23 2016
From: vicgeneral at iglesiadeasturias.org (Maria Reyes)
Date: Thu, 20 Oct 2016 22:10:23 +0800
Subject: ***~~BULK~~*** Re: 
Message-ID: <c8b5d4a6b4de837034e05b739e30fc16@iglesiadeasturias.org>

Your email won ?4,000,000.00 El Gordo (First Prize) in the End of year Spanish Christmas Lottery Bonanza 2016 (Loter?a de Navidad). Contact spanishlottery2016 at rogers.com to claim.


From geoff at infradead.org  Thu Oct 20 09:37:03 2016
From: geoff at infradead.org (Geoff Levand)
Date: Thu, 20 Oct 2016 09:37:03 -0700
Subject: [PATCH v2] arm64: Add support for additional relocations in the
 kexec purgatory code
In-Reply-To: <1476960211-25594-1-git-send-email-catalin.marinas@arm.com>
References: <1476960211-25594-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <2792b205-dfdd-1362-9cf4-d886472a9357@infradead.org>

On 10/20/2016 03:43 AM, Catalin Marinas wrote:
> When compiling the kexec-tools with gcc6, the following additional
> reolcations are generated in the purgatory.ro file:
> 
> R_AARCH64_ADR_PREL_PG_HI21
> R_AARCH64_ADD_ABS_LO12_NC
> R_AARCH64_LDST64_ABS_LO12_NC

Looks good.  Simon, please apply.

Reviewed-by: Geoff Levand <geoff at infradead.org>




From sgoel at codeaurora.org  Thu Oct 20 16:14:28 2016
From: sgoel at codeaurora.org (Sameer Goel)
Date: Thu, 20 Oct 2016 17:14:28 -0600
Subject: [PATCH] kexec: Increase the upper limit for RAM segments
Message-ID: <1477005268-26943-1-git-send-email-sgoel@codeaurora.org>

Change the current hardcoded values to 64 from 16.

Signed-off-by: Sameer Goel <sgoel at codeaurora.org>
---
 kexec/arch/arm64/kexec-arm64.h | 2 +-
 kexec/kexec-syscall.h          | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h
index bac62f8..bd4c20e 100644
--- a/kexec/arch/arm64/kexec-arm64.h
+++ b/kexec/arch/arm64/kexec-arm64.h
@@ -11,7 +11,7 @@
 #include "image-header.h"
 #include "kexec.h"
 
-#define KEXEC_SEGMENT_MAX 16
+#define KEXEC_SEGMENT_MAX 64
 
 #define BOOT_BLOCK_VERSION 17
 #define BOOT_BLOCK_LAST_COMP_VERSION 16
diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h
index c0d0bea..f84c937 100644
--- a/kexec/kexec-syscall.h
+++ b/kexec/kexec-syscall.h
@@ -115,7 +115,7 @@ static inline long kexec_file_load(int kernel_fd, int initrd_fd,
 #define KEXEC_ARCH_MIPS    ( 8 << 16)
 #define KEXEC_ARCH_CRIS    (76 << 16)
 
-#define KEXEC_MAX_SEGMENTS 16
+#define KEXEC_MAX_SEGMENTS 64
 
 #ifdef __i386__
 #define KEXEC_ARCH_NATIVE	KEXEC_ARCH_386
-- 
Qualcomm Datacenter Technologies as an affiliate of Qualcomm Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.



From f.fainelli at gmail.com  Thu Oct 20 18:15:16 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Thu, 20 Oct 2016 18:15:16 -0700
Subject: [PATCH] kexec: Export kexec_in_progress to modules
Message-ID: <1477012516-20470-1-git-send-email-f.fainelli@gmail.com>

The bcm_sf2 driver uses kexec_in_progress to know whether it can power
down an integrated PHY during shutdown, and can be built as a module.
Other modules may be using this in the future, so export it.

Fixes: 2399d6143f85 ("net: dsa: bcm_sf2: Prevent GPHY shutdown for kexec'd kernels")
Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
Eric, David, Stephen,

The offending commit is in David's net.git tree, so it would probably make
sense to route the fix through the same tree.

Thanks!

 kernel/kexec_core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 561675589511..786ab85a5452 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -59,6 +59,7 @@ size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
 
 /* Flag to indicate we are going to kexec a new kernel */
 bool kexec_in_progress = false;
+EXPORT_SYMBOL_GPL(kexec_in_progress);
 
 
 /* Location of the reserved area for the crash kernel */
-- 
2.7.4



From davem at davemloft.net  Thu Oct 20 18:54:10 2016
From: davem at davemloft.net (David Miller)
Date: Thu, 20 Oct 2016 21:54:10 -0400 (EDT)
Subject: [PATCH] kexec: Export kexec_in_progress to modules
In-Reply-To: <1477012516-20470-1-git-send-email-f.fainelli@gmail.com>
References: <1477012516-20470-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <20161020.215410.650162338407203719.davem@davemloft.net>

From: Florian Fainelli <f.fainelli at gmail.com>
Date: Thu, 20 Oct 2016 18:15:16 -0700

> The bcm_sf2 driver uses kexec_in_progress to know whether it can power
> down an integrated PHY during shutdown, and can be built as a module.
> Other modules may be using this in the future, so export it.
> 
> Fixes: 2399d6143f85 ("net: dsa: bcm_sf2: Prevent GPHY shutdown for kexec'd kernels")
> Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
> ---
> Eric, David, Stephen,
> 
> The offending commit is in David's net.git tree, so it would probably make
> sense to route the fix through the same tree.

Ok, I'll apply this, thanks Florian.


From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:40:07 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:40:07 -0200
Subject: [PATCH v9 00/10] kexec_file_load implementation for PowerPC
Message-ID: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>

Hello,

This version has the following changes:

1. Rebased on v4.9-rc1. This should fix the conflicts in next and -mm
   that these patches were having with the s/CONFIG_WORD_SIZE/BITS/ change.

2. Changed patch "powerpc: Factor out relocation code in module_64.c" to
   make as little changes as possible to arch/powerpc/module_64.c and
   <asm/module.h>. This meant factoring out only the switch statement from
   apply_relocate_add into its own function, and keeping it in module_64.c.
   arch_kexec_apply_relocations_add and apply_relocate_add share a bit less
   code now. This addresses a concern expressed by Michael Ellerman that
   there were too many changes being made to the module loading code.

3. Reduced number of patches in the series by squashing one patch and
   redistributing the code in two other patches. They were smaller after
   the change above and didn't make that much sense on their own anymore.

4. Moved code implementing kexec_file_load to a new file instead of adding
   it to the existing arch/powerpc/machine_kexec_64.c.

5. Cleaned up the purgatory code a bit to fix checkpatch warnings: removed
   unused code related to crashdump support and added __section(".data")
   to global variables instead of initializing them to zero to avoid them
   going to .bss.

The changes in 3. and 4. made the patches somewhat different from v8 but
it's just code moving from one patch to another, or to a new file. Apart
from what is described in 2. and 5., there's very little actual code
changed. The patches are all bisectable, each one was tested with
several kernel configs.

The gory details are in the detailed changelog at the end of this email.

Original cover letter:

This patch series implements the kexec_file_load system call on PowerPC.

This system call moves the reading of the kernel, initrd and the device tree
from the userspace kexec tool to the kernel. This is needed if you want to
do one or both of the following:

1. only allow loading of signed kernels.
2. "measure" (i.e., record the hashes of) the kernel, initrd, kernel
   command line and other boot inputs for the Integrity Measurement
   Architecture subsystem.

The above are the functions kexec already has built into kexec_file_load.
Yesterday I posted a set of patches which allows a third feature:

3. have IMA pass-on its event log (where integrity measurements are
   registered) accross kexec to the second kernel, so that the event
   history is preserved.

Because OpenPower uses an intermediary Linux instance as a boot loader
(skiroot), feature 1 is needed to implement secure boot for the platform,
while features 2 and 3 are needed to implement trusted boot.

This patch series starts by removing an x86 assumption from kexec_file:
kexec_add_buffer uses iomem to find reserved memory ranges, but PowerPC
uses the memblock subsystem.  A hook is added so that each arch can
specify how memory ranges can be found.

Also, the memory-walking logic in kexec_add_buffer is useful in this
implementation to find a free area for the purgatory's stack, so the
next patch moves that logic to kexec_locate_mem_hole.

The kexec_file_load system call needs to apply relocations to the
purgatory but adding code for that would duplicate functionality with
the module loading mechanism, which also needs to apply relocations to
the kernel modules.  Therefore, this patch series factors out the module
relocation code so that it can be shared.

One thing that is still missing is crashkernel support, which I intend
to submit shortly. For now, arch_kexec_kernel_image_probe rejects crash
kernels.

This code is based on kexec-tools, but with many modifications to adapt
it to the kernel environment and facilities. Except the purgatory,
which only has minimal changes.

Changes for v9:
- Rebased on top of v4.9-rc1
- Patch "powerpc: Change places using CONFIG_KEXEC to use CONFIG_KEXEC_CORE instead."
  - Fixed conflict with patch renaming CONFIG_WORD_SIZE to BITS.
- Patch "powerpc: Factor out relocation code from module_64.c to elf_util_64.c."
  - Retitled to "powerpc: Factor out relocation code in module_64.c"
  - Fixed conflict with patch renaming CONFIG_WORD_SIZE to BITS.
  - Put relocation code in function elf64_apply_relocate_add_item in
    module_64.c itself instead of moving it to elf_util_64.c.
  - Only factored out the switch statement to apply the relocations
    instead of the whole logic to iterate through all of the relocations.
  - There's no elf_util_64.c anymore.
  - Doesn't change <asm/module.h> anymore.
  - Doesn't change arch/powerpc/kernel/Makefile anymore.
  - Moved creation of <asm/elf_util.h> to patch "Implement kexec_file_load."
- Patch "powerpc: Generalize elf64_apply_relocate_add."
  - Dropped patch from series.
  - Moved changes adding address variable to patch "powerpc: Implement
    kexec_file_load."
- Patch "powerpc: Adapt elf64_apply_relocate_add for kexec_file_load."
  - Dropped patch from series.
  - Moved new relocs needed by the purgatory to patch "powerpc: Implement
    kexec_file_load."
- Patch "powerpc: Implement kexec_file_load."
  - Fixed conflict with patch renaming CONFIG_WORD_SIZE to BITS.
  - Put code in a new file machine_kexec_file_64.c instead of adding it to
    machine_kexec_64.c.
  - arch_kexec_apply_relocations_add now has the for loop which was
    previously factored out in elf64_apply_relocate_add.
  - Moved definition of setup_purgatory to "powerpc: Add support for
    loading ELF kernels with kexec_file_load.".
  - Introduce <asm/elf_util.h> and elf_util.c in this patch.
  - Only build elf_util.c if CONFIG_KEXEC_FILE=y.
  - Renamed my_r2 to elf_my_r2 and changed it to receive a pointer to
    struct elf_shdr instead of struct elf_info.
  - Added toc_section function.
  - Removed elf_init_elf_info function.
- Patch "powerpc: Add functions to read ELF files of any endianness."
  - Fixed conflict with patch renaming CONFIG_WORD_SIZE to BITS.
  - Introduce struct elf_info in this patch.
  - Removed stubs_section and toc_section from struct elf_info.
  - Doesn't change arch/powerpc/kernel/Makefile anymore.
- Patch "powerpc: Add code to work with device trees in kexec_file_load."
  - Squashed into "powerpc: Add support for loading ELF kernels with
    kexec_file_load.". The code is unchanged.
- Patch "powerpc: Add support for loading ELF kernels with kexec_file_load."
  - Fixed conflict with patch renaming CONFIG_WORD_SIZE to BITS.
  - Fixed uninitialized variable warning when building with GCC 4.6.3.
  - Don't create <asm/kexec_elf_64.h> anymore, put declaration of
    kexec_el_64_ops in <asm/kexec.h> instead.
  - Removed unused extern declaration of kexec_purgatory_size.
  - Made elf64_load static.
  - Factor out delete_fdt_mem_rsv from setup_new_fdt. This change was in
    the patch series for preserving IMA measurements accross kexec.
- Patch "powerpc: Add purgatory for kexec_file_load implementation."
  - Fixed conflict with patch renaming CONFIG_WORD_SIZE to BITS.
  - Changed purgatory Makefile to use the kernel KBUILD_CFLAGS, filtering
    out the flags for ftrace. (Michael Ellerman)
  - Added extern declaration of the debug global variable to purgatory.h and
    included it in console-ppc64.c to fix checkpatch.pl warning.
  - Added __section attribute to global variables in purgatory-ppc64.c and
    don't initialize them to zero, to fix checkpatch.pl warning.
  - Fixed type of debug global variable to int instead of unsigned int.
  - Included <linux/compiler.h> in purgatory.h and use __printf macro to
    fix checkpatch.pl warning.
  - Removed crashdump-ppc64.h, crashdump_backup.c and purgatory-ppc64.h.

Changes for v8:
- Rebased on top of v4.8-rc5.
- Patch "powerpc: Add purgatory for kexec_file_load implementation."
  - Fix cross build from ppc64 LE to BE and vice-versa.
  - Don't build the purgatory during archprepare.

Changes for v7:
- Rebased on top of v4.8-rc4.
- Patch "powerpc: Change places using CONFIG_KEXEC to use CONFIG_KEXEC_CORE
  instead."
  - New patch. Fixes build when CONFIG_KEXEC=n and CONFIG_KEXEC_FILE=y.
- Patch "powerpc: Adapt elf64_apply_relocate_add for kexec_file_load."
  - Fixed checkpatch warning "else is not generally useful after a break
    or return".
  - Fixed checkpatch warnings about line length. (Andrew Morton)
- Patch "powerpc: Add code to work with device trees in kexec_file_load."
  - Remove space before tabs in doc comment for setup_new_fdt. (Andrew Morton)
  - Fixed checkpatch warnings about line length.
- Patch "powerpc: Add support for loading ELF kernels with kexec_file_load."
  - Removed duplicate #include <linux/kexec.h>.

Changes for v6:
- Based directly on top of v4.8-rc1.
- Patch "powerpc: Adapt elf64_apply_relocate_add for kexec_file_load."
  - Allow undefined symbols if they are relocations for the TOC in the
    big endian ABI.
  - Fixed build error in this patch by adding the ehdr member to elf_info
    here instead of in the next patch.
  - Initialize elf_info.ehdr in module_64.c:module_frob_arch_sections.
- Patch "powerpc: Add code to work with device trees in kexec_file_load."
  - Changed find_debug_console to look for /chosen instead of receiving
    its offset as an argument.
  - setup_new_fdt: no need to find /chosen again after deleting the memory
    reservation for initrd.
- Patch "powerpc: Add support for loading ELF kernels with kexec_file_load."
  - Don't pass the offset to /chosen to find_debug_console.
- Patch "powerpc: Allow userspace to set device tree properties in kexec_file_load"
  - Dropped patch.
- Patch "powerpc: Add purgatory for kexec_file_load implementation."
  - Make boot/string.S use the DOTSYM macro so that it can be
    used by the ppc64 big endian purgatory.
  - Use -mcall-aixdesc to compile the purgatory on big endian ppc64.

Changes for v5:
- Rebased series on v4.8-rc1 + the extend kexec_file_load series.
- Patch "powerpc: Adapt elf64_apply_relocate_add for kexec_file_load."
  - New patch. These changes were previously in patch 10.
    The code itself is unchanged from v4.
- Patch "powerpc: Implement kexec_file_load."
  - Moved arch_kexec_walk_mem, arch_kexec_apply_relocations_add and
    setup_purgatory from patch 10 to this patch.
  - arch_kexec_apply_relocations_add is unchanged from v4.
  - Fixed off-by-one error in arch_kexec_walk_mem when passing range
    to func.
  - Moved setup_purgatory from kexec_elf_64.c to machine_kexec_64.c,
    and changed it to receive a pointer to the slave code directly
    rather than a struct elf_info and getting the pointer from there.
- Patch "powerpc: Add code to work with device trees in kexec_file_load."
  - New patch. These changes were previously in patch 10.
  - find_debug_console moved from kexec_elf_64.c to machine_kexec_64.c.
    The code is unchanged from v4.
  - setup_new_fdt is a new function factored out of elf64_load. The only
    code change from v4 is to create /chosen if it doesn't exist yet.
- Patch "powerpc: Add support for loading ELF kernels with kexec_file_load."
  - This patch was too big, so moved some of its changes to other patches
    to facilitate review.
  - Allow loading ELF file type ET_DYN, which is what the BE kernel uses.
  - The code adapting the device tree for booting the new kernel was moved
    out of elf64_load to setup_new_fdt.
- Patch "powerpc: Allow userspace to set device tree properties in kexec_file_load"
  - New patch.
  - The code in this patch didn't exist in v4.
  - This is the only patch that depends on the extend kexec_file_load series.
- Patch "powerpc: Enable CONFIG_KEXEC_FILE in powerpc server defconfigs."
  - New patch.


Thiago Jung Bauermann (10):
  kexec_file: Allow arch-specific memory walking for kexec_add_buffer
  kexec_file: Change kexec_add_buffer to take kexec_buf as argument.
  kexec_file: Factor out kexec_locate_mem_hole from kexec_add_buffer.
  powerpc: Change places using CONFIG_KEXEC to use CONFIG_KEXEC_CORE
    instead.
  powerpc: Factor out relocation code in module_64.c
  powerpc: Implement kexec_file_load.
  powerpc: Add functions to read ELF files of any endianness.
  powerpc: Add support for loading ELF kernels with kexec_file_load.
  powerpc: Add purgatory for kexec_file_load implementation.
  powerpc: Enable CONFIG_KEXEC_FILE in powerpc server defconfigs.

 arch/powerpc/Kconfig                          |  15 +-
 arch/powerpc/Makefile                         |   1 +
 arch/powerpc/boot/string.S                    |  67 +--
 arch/powerpc/configs/powernv_defconfig        |   2 +
 arch/powerpc/configs/ppc64_defconfig          |   2 +
 arch/powerpc/configs/pseries_defconfig        |   2 +
 arch/powerpc/include/asm/debug.h              |   2 +-
 arch/powerpc/include/asm/elf_util.h           |  64 +++
 arch/powerpc/include/asm/kexec.h              |  18 +-
 arch/powerpc/include/asm/machdep.h            |   4 +-
 arch/powerpc/include/asm/smp.h                |   2 +-
 arch/powerpc/include/asm/systbl.h             |   1 +
 arch/powerpc/include/asm/unistd.h             |   2 +-
 arch/powerpc/include/uapi/asm/unistd.h        |   1 +
 arch/powerpc/kernel/Makefile                  |   6 +-
 arch/powerpc/kernel/elf_util.c                | 464 +++++++++++++++++++++
 arch/powerpc/kernel/head_64.S                 |   2 +-
 arch/powerpc/kernel/kexec_elf_64.c            | 280 +++++++++++++
 arch/powerpc/kernel/machine_kexec_file_64.c   | 579 ++++++++++++++++++++++++++
 arch/powerpc/kernel/misc_32.S                 |   2 +-
 arch/powerpc/kernel/misc_64.S                 |   6 +-
 arch/powerpc/kernel/module_64.c               | 383 ++++++++++-------
 arch/powerpc/kernel/prom.c                    |   2 +-
 arch/powerpc/kernel/setup_64.c                |   4 +-
 arch/powerpc/kernel/smp.c                     |   6 +-
 arch/powerpc/kernel/traps.c                   |   2 +-
 arch/powerpc/platforms/85xx/corenet_generic.c |   2 +-
 arch/powerpc/platforms/85xx/smp.c             |   8 +-
 arch/powerpc/platforms/cell/spu_base.c        |   2 +-
 arch/powerpc/platforms/powernv/setup.c        |   6 +-
 arch/powerpc/platforms/ps3/setup.c            |   4 +-
 arch/powerpc/platforms/pseries/Makefile       |   2 +-
 arch/powerpc/platforms/pseries/setup.c        |   4 +-
 arch/powerpc/purgatory/.gitignore             |   2 +
 arch/powerpc/purgatory/Makefile               |  33 ++
 arch/powerpc/purgatory/console-ppc64.c        |  37 ++
 arch/powerpc/purgatory/crtsavres.S            |   5 +
 arch/powerpc/purgatory/hvCall.S               |  27 ++
 arch/powerpc/purgatory/hvCall.h               |   8 +
 arch/powerpc/purgatory/kexec-sha256.h         |  11 +
 arch/powerpc/purgatory/ppc64_asm.h            |  20 +
 arch/powerpc/purgatory/printf.c               | 164 ++++++++
 arch/powerpc/purgatory/purgatory-ppc64.c      |  36 ++
 arch/powerpc/purgatory/purgatory.c            |  62 +++
 arch/powerpc/purgatory/purgatory.h            |  14 +
 arch/powerpc/purgatory/sha256.c               |   6 +
 arch/powerpc/purgatory/sha256.h               |   1 +
 arch/powerpc/purgatory/string.S               |   2 +
 arch/powerpc/purgatory/v2wrap.S               | 134 ++++++
 arch/x86/kernel/crash.c                       |  37 +-
 arch/x86/kernel/kexec-bzimage64.c             |  48 ++-
 include/linux/kexec.h                         |  36 +-
 kernel/kexec_file.c                           | 141 ++++---
 kernel/kexec_internal.h                       |  16 -
 54 files changed, 2437 insertions(+), 350 deletions(-)
 create mode 100644 arch/powerpc/include/asm/elf_util.h
 create mode 100644 arch/powerpc/kernel/elf_util.c
 create mode 100644 arch/powerpc/kernel/kexec_elf_64.c
 create mode 100644 arch/powerpc/kernel/machine_kexec_file_64.c
 create mode 100644 arch/powerpc/purgatory/.gitignore
 create mode 100644 arch/powerpc/purgatory/Makefile
 create mode 100644 arch/powerpc/purgatory/console-ppc64.c
 create mode 100644 arch/powerpc/purgatory/crtsavres.S
 create mode 100644 arch/powerpc/purgatory/hvCall.S
 create mode 100644 arch/powerpc/purgatory/hvCall.h
 create mode 100644 arch/powerpc/purgatory/kexec-sha256.h
 create mode 100644 arch/powerpc/purgatory/ppc64_asm.h
 create mode 100644 arch/powerpc/purgatory/printf.c
 create mode 100644 arch/powerpc/purgatory/purgatory-ppc64.c
 create mode 100644 arch/powerpc/purgatory/purgatory.c
 create mode 100644 arch/powerpc/purgatory/purgatory.h
 create mode 100644 arch/powerpc/purgatory/sha256.c
 create mode 100644 arch/powerpc/purgatory/sha256.h
 create mode 100644 arch/powerpc/purgatory/string.S
 create mode 100644 arch/powerpc/purgatory/v2wrap.S

-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:40:08 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:40:08 -0200
Subject: [PATCH v9 01/10] kexec_file: Allow arch-specific memory walking for
 kexec_add_buffer
In-Reply-To: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017617-8540-2-git-send-email-bauerman@linux.vnet.ibm.com>

Allow architectures to specify a different memory walking function for
kexec_add_buffer. x86 uses iomem to track reserved memory ranges, but
PowerPC uses the memblock subsystem.

Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
Acked-by: Dave Young <dyoung at redhat.com>
Acked-by: Balbir Singh <bsingharora at gmail.com>
---
 include/linux/kexec.h   | 29 ++++++++++++++++++++++++++++-
 kernel/kexec_file.c     | 30 ++++++++++++++++++++++--------
 kernel/kexec_internal.h | 16 ----------------
 3 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 406c33dcae13..5e320ddaaa82 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -148,7 +148,34 @@ struct kexec_file_ops {
 	kexec_verify_sig_t *verify_sig;
 #endif
 };
-#endif
+
+/**
+ * struct kexec_buf - parameters for finding a place for a buffer in memory
+ * @image:	kexec image in which memory to search.
+ * @buffer:	Contents which will be copied to the allocated memory.
+ * @bufsz:	Size of @buffer.
+ * @mem:	On return will have address of the buffer in memory.
+ * @memsz:	Size for the buffer in memory.
+ * @buf_align:	Minimum alignment needed.
+ * @buf_min:	The buffer can't be placed below this address.
+ * @buf_max:	The buffer can't be placed above this address.
+ * @top_down:	Allocate from top of memory.
+ */
+struct kexec_buf {
+	struct kimage *image;
+	char *buffer;
+	unsigned long bufsz;
+	unsigned long mem;
+	unsigned long memsz;
+	unsigned long buf_align;
+	unsigned long buf_min;
+	unsigned long buf_max;
+	bool top_down;
+};
+
+int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
+			       int (*func)(u64, u64, void *));
+#endif /* CONFIG_KEXEC_FILE */
 
 struct kimage {
 	kimage_entry_t head;
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 037c321c5618..f865674bff51 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -428,6 +428,27 @@ static int locate_mem_hole_callback(u64 start, u64 end, void *arg)
 	return locate_mem_hole_bottom_up(start, end, kbuf);
 }
 
+/**
+ * arch_kexec_walk_mem - call func(data) on free memory regions
+ * @kbuf:	Context info for the search. Also passed to @func.
+ * @func:	Function to call for each memory region.
+ *
+ * Return: The memory walk will stop when func returns a non-zero value
+ * and that value will be returned. If all free regions are visited without
+ * func returning non-zero, then zero will be returned.
+ */
+int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
+			       int (*func)(u64, u64, void *))
+{
+	if (kbuf->image->type == KEXEC_TYPE_CRASH)
+		return walk_iomem_res_desc(crashk_res.desc,
+					   IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY,
+					   crashk_res.start, crashk_res.end,
+					   kbuf, func);
+	else
+		return walk_system_ram_res(0, ULONG_MAX, kbuf, func);
+}
+
 /*
  * Helper function for placing a buffer in a kexec segment. This assumes
  * that kexec_mutex is held.
@@ -474,14 +495,7 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
 	kbuf->top_down = top_down;
 
 	/* Walk the RAM ranges and allocate a suitable range for the buffer */
-	if (image->type == KEXEC_TYPE_CRASH)
-		ret = walk_iomem_res_desc(crashk_res.desc,
-				IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY,
-				crashk_res.start, crashk_res.end, kbuf,
-				locate_mem_hole_callback);
-	else
-		ret = walk_system_ram_res(0, -1, kbuf,
-					  locate_mem_hole_callback);
+	ret = arch_kexec_walk_mem(kbuf, locate_mem_hole_callback);
 	if (ret != 1) {
 		/* A suitable memory range could not be found for buffer */
 		return -EADDRNOTAVAIL;
diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h
index 0a52315d9c62..4cef7e4706b0 100644
--- a/kernel/kexec_internal.h
+++ b/kernel/kexec_internal.h
@@ -20,22 +20,6 @@ struct kexec_sha_region {
 	unsigned long len;
 };
 
-/*
- * Keeps track of buffer parameters as provided by caller for requesting
- * memory placement of buffer.
- */
-struct kexec_buf {
-	struct kimage *image;
-	char *buffer;
-	unsigned long bufsz;
-	unsigned long mem;
-	unsigned long memsz;
-	unsigned long buf_align;
-	unsigned long buf_min;
-	unsigned long buf_max;
-	bool top_down;		/* allocate from top of memory hole */
-};
-
 void kimage_file_post_load_cleanup(struct kimage *image);
 #else /* CONFIG_KEXEC_FILE */
 static inline void kimage_file_post_load_cleanup(struct kimage *image) { }
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:40:09 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:40:09 -0200
Subject: [PATCH v9 02/10] kexec_file: Change kexec_add_buffer to take
 kexec_buf as argument.
In-Reply-To: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017617-8540-3-git-send-email-bauerman@linux.vnet.ibm.com>

This is done to simplify the kexec_add_buffer argument list.
Adapt all callers to set up a kexec_buf to pass to kexec_add_buffer.

In addition, change the type of kexec_buf.buffer from char * to void *.
There is no particular reason for it to be a char *, and the change
allows us to get rid of 3 existing casts to char * in the code.

Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
Acked-by: Dave Young <dyoung at redhat.com>
Acked-by: Balbir Singh <bsingharora at gmail.com>
---
 arch/x86/kernel/crash.c           | 37 ++++++++--------
 arch/x86/kernel/kexec-bzimage64.c | 48 +++++++++++----------
 include/linux/kexec.h             |  8 +---
 kernel/kexec_file.c               | 88 ++++++++++++++++++---------------------
 4 files changed, 87 insertions(+), 94 deletions(-)

diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index 650830e39e3a..3741461c63a0 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -631,9 +631,9 @@ static int determine_backup_region(u64 start, u64 end, void *arg)
 
 int crash_load_segments(struct kimage *image)
 {
-	unsigned long src_start, src_sz, elf_sz;
-	void *elf_addr;
 	int ret;
+	struct kexec_buf kbuf = { .image = image, .buf_min = 0,
+				  .buf_max = ULONG_MAX, .top_down = false };
 
 	/*
 	 * Determine and load a segment for backup area. First 640K RAM
@@ -647,43 +647,44 @@ int crash_load_segments(struct kimage *image)
 	if (ret < 0)
 		return ret;
 
-	src_start = image->arch.backup_src_start;
-	src_sz = image->arch.backup_src_sz;
-
 	/* Add backup segment. */
-	if (src_sz) {
+	if (image->arch.backup_src_sz) {
+		kbuf.buffer = &crash_zero_bytes;
+		kbuf.bufsz = sizeof(crash_zero_bytes);
+		kbuf.memsz = image->arch.backup_src_sz;
+		kbuf.buf_align = PAGE_SIZE;
 		/*
 		 * Ideally there is no source for backup segment. This is
 		 * copied in purgatory after crash. Just add a zero filled
 		 * segment for now to make sure checksum logic works fine.
 		 */
-		ret = kexec_add_buffer(image, (char *)&crash_zero_bytes,
-				       sizeof(crash_zero_bytes), src_sz,
-				       PAGE_SIZE, 0, -1, 0,
-				       &image->arch.backup_load_addr);
+		ret = kexec_add_buffer(&kbuf);
 		if (ret)
 			return ret;
+		image->arch.backup_load_addr = kbuf.mem;
 		pr_debug("Loaded backup region at 0x%lx backup_start=0x%lx memsz=0x%lx\n",
-			 image->arch.backup_load_addr, src_start, src_sz);
+			 image->arch.backup_load_addr,
+			 image->arch.backup_src_start, kbuf.memsz);
 	}
 
 	/* Prepare elf headers and add a segment */
-	ret = prepare_elf_headers(image, &elf_addr, &elf_sz);
+	ret = prepare_elf_headers(image, &kbuf.buffer, &kbuf.bufsz);
 	if (ret)
 		return ret;
 
-	image->arch.elf_headers = elf_addr;
-	image->arch.elf_headers_sz = elf_sz;
+	image->arch.elf_headers = kbuf.buffer;
+	image->arch.elf_headers_sz = kbuf.bufsz;
 
-	ret = kexec_add_buffer(image, (char *)elf_addr, elf_sz, elf_sz,
-			ELF_CORE_HEADER_ALIGN, 0, -1, 0,
-			&image->arch.elf_load_addr);
+	kbuf.memsz = kbuf.bufsz;
+	kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
+	ret = kexec_add_buffer(&kbuf);
 	if (ret) {
 		vfree((void *)image->arch.elf_headers);
 		return ret;
 	}
+	image->arch.elf_load_addr = kbuf.mem;
 	pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
-		 image->arch.elf_load_addr, elf_sz, elf_sz);
+		 image->arch.elf_load_addr, kbuf.bufsz, kbuf.bufsz);
 
 	return ret;
 }
diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
index 3407b148c240..d0a814a9d96a 100644
--- a/arch/x86/kernel/kexec-bzimage64.c
+++ b/arch/x86/kernel/kexec-bzimage64.c
@@ -331,17 +331,17 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 
 	struct setup_header *header;
 	int setup_sects, kern16_size, ret = 0;
-	unsigned long setup_header_size, params_cmdline_sz, params_misc_sz;
+	unsigned long setup_header_size, params_cmdline_sz;
 	struct boot_params *params;
 	unsigned long bootparam_load_addr, kernel_load_addr, initrd_load_addr;
 	unsigned long purgatory_load_addr;
-	unsigned long kernel_bufsz, kernel_memsz, kernel_align;
-	char *kernel_buf;
 	struct bzimage64_data *ldata;
 	struct kexec_entry64_regs regs64;
 	void *stack;
 	unsigned int setup_hdr_offset = offsetof(struct boot_params, hdr);
 	unsigned int efi_map_offset, efi_map_sz, efi_setup_data_offset;
+	struct kexec_buf kbuf = { .image = image, .buf_max = ULONG_MAX,
+				  .top_down = true };
 
 	header = (struct setup_header *)(kernel + setup_hdr_offset);
 	setup_sects = header->setup_sects;
@@ -402,11 +402,11 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 	params_cmdline_sz = sizeof(struct boot_params) + cmdline_len +
 				MAX_ELFCOREHDR_STR_LEN;
 	params_cmdline_sz = ALIGN(params_cmdline_sz, 16);
-	params_misc_sz = params_cmdline_sz + efi_map_sz +
+	kbuf.bufsz = params_cmdline_sz + efi_map_sz +
 				sizeof(struct setup_data) +
 				sizeof(struct efi_setup_data);
 
-	params = kzalloc(params_misc_sz, GFP_KERNEL);
+	params = kzalloc(kbuf.bufsz, GFP_KERNEL);
 	if (!params)
 		return ERR_PTR(-ENOMEM);
 	efi_map_offset = params_cmdline_sz;
@@ -418,37 +418,41 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
 	/* Is there a limit on setup header size? */
 	memcpy(&params->hdr, (kernel + setup_hdr_offset), setup_header_size);
 
-	ret = kexec_add_buffer(image, (char *)params, params_misc_sz,
-			       params_misc_sz, 16, MIN_BOOTPARAM_ADDR,
-			       ULONG_MAX, 1, &bootparam_load_addr);
+	kbuf.buffer = params;
+	kbuf.memsz = kbuf.bufsz;
+	kbuf.buf_align = 16;
+	kbuf.buf_min = MIN_BOOTPARAM_ADDR;
+	ret = kexec_add_buffer(&kbuf);
 	if (ret)
 		goto out_free_params;
+	bootparam_load_addr = kbuf.mem;
 	pr_debug("Loaded boot_param, command line and misc at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
-		 bootparam_load_addr, params_misc_sz, params_misc_sz);
+		 bootparam_load_addr, kbuf.bufsz, kbuf.bufsz);
 
 	/* Load kernel */
-	kernel_buf = kernel + kern16_size;
-	kernel_bufsz =  kernel_len - kern16_size;
-	kernel_memsz = PAGE_ALIGN(header->init_size);
-	kernel_align = header->kernel_alignment;
-
-	ret = kexec_add_buffer(image, kernel_buf,
-			       kernel_bufsz, kernel_memsz, kernel_align,
-			       MIN_KERNEL_LOAD_ADDR, ULONG_MAX, 1,
-			       &kernel_load_addr);
+	kbuf.buffer = kernel + kern16_size;
+	kbuf.bufsz =  kernel_len - kern16_size;
+	kbuf.memsz = PAGE_ALIGN(header->init_size);
+	kbuf.buf_align = header->kernel_alignment;
+	kbuf.buf_min = MIN_KERNEL_LOAD_ADDR;
+	ret = kexec_add_buffer(&kbuf);
 	if (ret)
 		goto out_free_params;
+	kernel_load_addr = kbuf.mem;
 
 	pr_debug("Loaded 64bit kernel at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
-		 kernel_load_addr, kernel_memsz, kernel_memsz);
+		 kernel_load_addr, kbuf.bufsz, kbuf.memsz);
 
 	/* Load initrd high */
 	if (initrd) {
-		ret = kexec_add_buffer(image, initrd, initrd_len, initrd_len,
-				       PAGE_SIZE, MIN_INITRD_LOAD_ADDR,
-				       ULONG_MAX, 1, &initrd_load_addr);
+		kbuf.buffer = initrd;
+		kbuf.bufsz = kbuf.memsz = initrd_len;
+		kbuf.buf_align = PAGE_SIZE;
+		kbuf.buf_min = MIN_INITRD_LOAD_ADDR;
+		ret = kexec_add_buffer(&kbuf);
 		if (ret)
 			goto out_free_params;
+		initrd_load_addr = kbuf.mem;
 
 		pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
 				initrd_load_addr, initrd_len, initrd_len);
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 5e320ddaaa82..437ef1b47428 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -163,7 +163,7 @@ struct kexec_file_ops {
  */
 struct kexec_buf {
 	struct kimage *image;
-	char *buffer;
+	void *buffer;
 	unsigned long bufsz;
 	unsigned long mem;
 	unsigned long memsz;
@@ -175,6 +175,7 @@ struct kexec_buf {
 
 int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
 			       int (*func)(u64, u64, void *));
+extern int kexec_add_buffer(struct kexec_buf *kbuf);
 #endif /* CONFIG_KEXEC_FILE */
 
 struct kimage {
@@ -239,11 +240,6 @@ extern asmlinkage long sys_kexec_load(unsigned long entry,
 					struct kexec_segment __user *segments,
 					unsigned long flags);
 extern int kernel_kexec(void);
-extern int kexec_add_buffer(struct kimage *image, char *buffer,
-			    unsigned long bufsz, unsigned long memsz,
-			    unsigned long buf_align, unsigned long buf_min,
-			    unsigned long buf_max, bool top_down,
-			    unsigned long *load_addr);
 extern struct page *kimage_alloc_control_pages(struct kimage *image,
 						unsigned int order);
 extern int kexec_load_purgatory(struct kimage *image, unsigned long min,
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index f865674bff51..efd2c094af7e 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -449,25 +449,27 @@ int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
 		return walk_system_ram_res(0, ULONG_MAX, kbuf, func);
 }
 
-/*
- * Helper function for placing a buffer in a kexec segment. This assumes
- * that kexec_mutex is held.
+/**
+ * kexec_add_buffer - place a buffer in a kexec segment
+ * @kbuf:	Buffer contents and memory parameters.
+ *
+ * This function assumes that kexec_mutex is held.
+ * On successful return, @kbuf->mem will have the physical address of
+ * the buffer in memory.
+ *
+ * Return: 0 on success, negative errno on error.
  */
-int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
-		     unsigned long memsz, unsigned long buf_align,
-		     unsigned long buf_min, unsigned long buf_max,
-		     bool top_down, unsigned long *load_addr)
+int kexec_add_buffer(struct kexec_buf *kbuf)
 {
 
 	struct kexec_segment *ksegment;
-	struct kexec_buf buf, *kbuf;
 	int ret;
 
 	/* Currently adding segment this way is allowed only in file mode */
-	if (!image->file_mode)
+	if (!kbuf->image->file_mode)
 		return -EINVAL;
 
-	if (image->nr_segments >= KEXEC_SEGMENT_MAX)
+	if (kbuf->image->nr_segments >= KEXEC_SEGMENT_MAX)
 		return -EINVAL;
 
 	/*
@@ -477,22 +479,14 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
 	 * logic goes through list of segments to make sure there are
 	 * no destination overlaps.
 	 */
-	if (!list_empty(&image->control_pages)) {
+	if (!list_empty(&kbuf->image->control_pages)) {
 		WARN_ON(1);
 		return -EINVAL;
 	}
 
-	memset(&buf, 0, sizeof(struct kexec_buf));
-	kbuf = &buf;
-	kbuf->image = image;
-	kbuf->buffer = buffer;
-	kbuf->bufsz = bufsz;
-
-	kbuf->memsz = ALIGN(memsz, PAGE_SIZE);
-	kbuf->buf_align = max(buf_align, PAGE_SIZE);
-	kbuf->buf_min = buf_min;
-	kbuf->buf_max = buf_max;
-	kbuf->top_down = top_down;
+	/* Ensure minimum alignment needed for segments. */
+	kbuf->memsz = ALIGN(kbuf->memsz, PAGE_SIZE);
+	kbuf->buf_align = max(kbuf->buf_align, PAGE_SIZE);
 
 	/* Walk the RAM ranges and allocate a suitable range for the buffer */
 	ret = arch_kexec_walk_mem(kbuf, locate_mem_hole_callback);
@@ -502,13 +496,12 @@ int kexec_add_buffer(struct kimage *image, char *buffer, unsigned long bufsz,
 	}
 
 	/* Found a suitable memory range */
-	ksegment = &image->segment[image->nr_segments];
+	ksegment = &kbuf->image->segment[kbuf->image->nr_segments];
 	ksegment->kbuf = kbuf->buffer;
 	ksegment->bufsz = kbuf->bufsz;
 	ksegment->mem = kbuf->mem;
 	ksegment->memsz = kbuf->memsz;
-	image->nr_segments++;
-	*load_addr = ksegment->mem;
+	kbuf->image->nr_segments++;
 	return 0;
 }
 
@@ -630,13 +623,15 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
 				  unsigned long max, int top_down)
 {
 	struct purgatory_info *pi = &image->purgatory_info;
-	unsigned long align, buf_align, bss_align, buf_sz, bss_sz, bss_pad;
-	unsigned long memsz, entry, load_addr, curr_load_addr, bss_addr, offset;
+	unsigned long align, bss_align, bss_sz, bss_pad;
+	unsigned long entry, load_addr, curr_load_addr, bss_addr, offset;
 	unsigned char *buf_addr, *src;
 	int i, ret = 0, entry_sidx = -1;
 	const Elf_Shdr *sechdrs_c;
 	Elf_Shdr *sechdrs = NULL;
-	void *purgatory_buf = NULL;
+	struct kexec_buf kbuf = { .image = image, .bufsz = 0, .buf_align = 1,
+				  .buf_min = min, .buf_max = max,
+				  .top_down = top_down };
 
 	/*
 	 * sechdrs_c points to section headers in purgatory and are read
@@ -702,9 +697,7 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
 	}
 
 	/* Determine how much memory is needed to load relocatable object. */
-	buf_align = 1;
 	bss_align = 1;
-	buf_sz = 0;
 	bss_sz = 0;
 
 	for (i = 0; i < pi->ehdr->e_shnum; i++) {
@@ -713,10 +706,10 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
 
 		align = sechdrs[i].sh_addralign;
 		if (sechdrs[i].sh_type != SHT_NOBITS) {
-			if (buf_align < align)
-				buf_align = align;
-			buf_sz = ALIGN(buf_sz, align);
-			buf_sz += sechdrs[i].sh_size;
+			if (kbuf.buf_align < align)
+				kbuf.buf_align = align;
+			kbuf.bufsz = ALIGN(kbuf.bufsz, align);
+			kbuf.bufsz += sechdrs[i].sh_size;
 		} else {
 			/* bss section */
 			if (bss_align < align)
@@ -728,32 +721,31 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
 
 	/* Determine the bss padding required to align bss properly */
 	bss_pad = 0;
-	if (buf_sz & (bss_align - 1))
-		bss_pad = bss_align - (buf_sz & (bss_align - 1));
+	if (kbuf.bufsz & (bss_align - 1))
+		bss_pad = bss_align - (kbuf.bufsz & (bss_align - 1));
 
-	memsz = buf_sz + bss_pad + bss_sz;
+	kbuf.memsz = kbuf.bufsz + bss_pad + bss_sz;
 
 	/* Allocate buffer for purgatory */
-	purgatory_buf = vzalloc(buf_sz);
-	if (!purgatory_buf) {
+	kbuf.buffer = vzalloc(kbuf.bufsz);
+	if (!kbuf.buffer) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	if (buf_align < bss_align)
-		buf_align = bss_align;
+	if (kbuf.buf_align < bss_align)
+		kbuf.buf_align = bss_align;
 
 	/* Add buffer to segment list */
-	ret = kexec_add_buffer(image, purgatory_buf, buf_sz, memsz,
-				buf_align, min, max, top_down,
-				&pi->purgatory_load_addr);
+	ret = kexec_add_buffer(&kbuf);
 	if (ret)
 		goto out;
+	pi->purgatory_load_addr = kbuf.mem;
 
 	/* Load SHF_ALLOC sections */
-	buf_addr = purgatory_buf;
+	buf_addr = kbuf.buffer;
 	load_addr = curr_load_addr = pi->purgatory_load_addr;
-	bss_addr = load_addr + buf_sz + bss_pad;
+	bss_addr = load_addr + kbuf.bufsz + bss_pad;
 
 	for (i = 0; i < pi->ehdr->e_shnum; i++) {
 		if (!(sechdrs[i].sh_flags & SHF_ALLOC))
@@ -799,11 +791,11 @@ static int __kexec_load_purgatory(struct kimage *image, unsigned long min,
 	 * Used later to identify which section is purgatory and skip it
 	 * from checksumming.
 	 */
-	pi->purgatory_buf = purgatory_buf;
+	pi->purgatory_buf = kbuf.buffer;
 	return ret;
 out:
 	vfree(sechdrs);
-	vfree(purgatory_buf);
+	vfree(kbuf.buffer);
 	return ret;
 }
 
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:40:10 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:40:10 -0200
Subject: [PATCH v9 03/10] kexec_file: Factor out kexec_locate_mem_hole from
 kexec_add_buffer.
In-Reply-To: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017617-8540-4-git-send-email-bauerman@linux.vnet.ibm.com>

kexec_locate_mem_hole will be used by the PowerPC kexec_file_load
implementation to find free memory for the purgatory stack.

Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
Acked-by: Dave Young <dyoung at redhat.com>
---
 include/linux/kexec.h |  1 +
 kernel/kexec_file.c   | 25 ++++++++++++++++++++-----
 2 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index 437ef1b47428..a33f63351f86 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -176,6 +176,7 @@ struct kexec_buf {
 int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
 			       int (*func)(u64, u64, void *));
 extern int kexec_add_buffer(struct kexec_buf *kbuf);
+int kexec_locate_mem_hole(struct kexec_buf *kbuf);
 #endif /* CONFIG_KEXEC_FILE */
 
 struct kimage {
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index efd2c094af7e..0c2df7f73792 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -450,6 +450,23 @@ int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
 }
 
 /**
+ * kexec_locate_mem_hole - find free memory for the purgatory or the next kernel
+ * @kbuf:	Parameters for the memory search.
+ *
+ * On success, kbuf->mem will have the start address of the memory region found.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int kexec_locate_mem_hole(struct kexec_buf *kbuf)
+{
+	int ret;
+
+	ret = arch_kexec_walk_mem(kbuf, locate_mem_hole_callback);
+
+	return ret == 1 ? 0 : -EADDRNOTAVAIL;
+}
+
+/**
  * kexec_add_buffer - place a buffer in a kexec segment
  * @kbuf:	Buffer contents and memory parameters.
  *
@@ -489,11 +506,9 @@ int kexec_add_buffer(struct kexec_buf *kbuf)
 	kbuf->buf_align = max(kbuf->buf_align, PAGE_SIZE);
 
 	/* Walk the RAM ranges and allocate a suitable range for the buffer */
-	ret = arch_kexec_walk_mem(kbuf, locate_mem_hole_callback);
-	if (ret != 1) {
-		/* A suitable memory range could not be found for buffer */
-		return -EADDRNOTAVAIL;
-	}
+	ret = kexec_locate_mem_hole(kbuf);
+	if (ret)
+		return ret;
 
 	/* Found a suitable memory range */
 	ksegment = &kbuf->image->segment[kbuf->image->nr_segments];
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:40:11 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:40:11 -0200
Subject: [PATCH v9 04/10] powerpc: Change places using CONFIG_KEXEC to use
 CONFIG_KEXEC_CORE instead.
In-Reply-To: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017617-8540-5-git-send-email-bauerman@linux.vnet.ibm.com>

Commit 2965faa5e03d ("kexec: split kexec_load syscall from kexec core
code") introduced CONFIG_KEXEC_CORE so that CONFIG_KEXEC means whether
the kexec_load system call should be compiled-in and CONFIG_KEXEC_FILE
means whether the kexec_file_load system call should be compiled-in.
These options can be set independently from each other.

Since until now powerpc only supported kexec_load, CONFIG_KEXEC and
CONFIG_KEXEC_CORE were synonyms. That is not the case anymore, so we
need to make a distinction. Almost all places where CONFIG_KEXEC was
being used should be using CONFIG_KEXEC_CORE instead, since
kexec_file_load also needs that code compiled in.

Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
---
 arch/powerpc/Kconfig                          | 2 +-
 arch/powerpc/include/asm/debug.h              | 2 +-
 arch/powerpc/include/asm/kexec.h              | 6 +++---
 arch/powerpc/include/asm/machdep.h            | 4 ++--
 arch/powerpc/include/asm/smp.h                | 2 +-
 arch/powerpc/kernel/Makefile                  | 4 ++--
 arch/powerpc/kernel/head_64.S                 | 2 +-
 arch/powerpc/kernel/misc_32.S                 | 2 +-
 arch/powerpc/kernel/misc_64.S                 | 6 +++---
 arch/powerpc/kernel/prom.c                    | 2 +-
 arch/powerpc/kernel/setup_64.c                | 4 ++--
 arch/powerpc/kernel/smp.c                     | 6 +++---
 arch/powerpc/kernel/traps.c                   | 2 +-
 arch/powerpc/platforms/85xx/corenet_generic.c | 2 +-
 arch/powerpc/platforms/85xx/smp.c             | 8 ++++----
 arch/powerpc/platforms/cell/spu_base.c        | 2 +-
 arch/powerpc/platforms/powernv/setup.c        | 6 +++---
 arch/powerpc/platforms/ps3/setup.c            | 4 ++--
 arch/powerpc/platforms/pseries/Makefile       | 2 +-
 arch/powerpc/platforms/pseries/setup.c        | 4 ++--
 20 files changed, 36 insertions(+), 36 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 65fba4c34cd7..6cb59c6e5ba4 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -489,7 +489,7 @@ config CRASH_DUMP
 
 config FA_DUMP
 	bool "Firmware-assisted dump"
-	depends on PPC64 && PPC_RTAS && CRASH_DUMP && KEXEC
+	depends on PPC64 && PPC_RTAS && CRASH_DUMP && KEXEC_CORE
 	help
 	  A robust mechanism to get reliable kernel crash dump with
 	  assistance from firmware. This approach does not use kexec,
diff --git a/arch/powerpc/include/asm/debug.h b/arch/powerpc/include/asm/debug.h
index a954e4975049..86308f177f2d 100644
--- a/arch/powerpc/include/asm/debug.h
+++ b/arch/powerpc/include/asm/debug.h
@@ -10,7 +10,7 @@ struct pt_regs;
 
 extern struct dentry *powerpc_debugfs_root;
 
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC_CORE)
 
 extern int (*__debugger)(struct pt_regs *regs);
 extern int (*__debugger_ipi)(struct pt_regs *regs);
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index a46f5f45570c..eca2f975bf44 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -53,7 +53,7 @@
 
 typedef void (*crash_shutdown_t)(void);
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 
 /*
  * This function is responsible for capturing register states if coming
@@ -91,7 +91,7 @@ static inline bool kdump_in_progress(void)
 	return crashing_cpu >= 0;
 }
 
-#else /* !CONFIG_KEXEC */
+#else /* !CONFIG_KEXEC_CORE */
 static inline void crash_kexec_secondary(struct pt_regs *regs) { }
 
 static inline int overlaps_crashkernel(unsigned long start, unsigned long size)
@@ -116,7 +116,7 @@ static inline bool kdump_in_progress(void)
 	return false;
 }
 
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
 #endif /* ! __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_KEXEC_H */
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index e02cbc6a6c70..5011b69107a7 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -183,7 +183,7 @@ struct machdep_calls {
 	 */
 	void (*machine_shutdown)(void);
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	void (*kexec_cpu_down)(int crash_shutdown, int secondary);
 
 	/* Called to do what every setup is needed on image and the
@@ -198,7 +198,7 @@ struct machdep_calls {
 	 * no return.
 	 */
 	void (*machine_kexec)(struct kimage *image);
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
 
 #ifdef CONFIG_SUSPEND
 	/* These are called to disable and enable, respectively, IRQs when
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 0d02c11dc331..32db16d2e7ad 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -176,7 +176,7 @@ static inline void set_hard_smp_processor_id(int cpu, int phys)
 #endif /* !CONFIG_SMP */
 #endif /* !CONFIG_PPC64 */
 
-#if defined(CONFIG_PPC64) && (defined(CONFIG_SMP) || defined(CONFIG_KEXEC))
+#if defined(CONFIG_PPC64) && (defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE))
 extern void smp_release_cpus(void);
 #else
 static inline void smp_release_cpus(void) { };
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 1925341dbb9c..22534a56c914 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -107,7 +107,7 @@ pci64-$(CONFIG_PPC64)		+= pci_dn.o pci-hotplug.o isa-bridge.o
 obj-$(CONFIG_PCI)		+= pci_$(BITS).o $(pci64-y) \
 				   pci-common.o pci_of_scan.o
 obj-$(CONFIG_PCI_MSI)		+= msi.o
-obj-$(CONFIG_KEXEC)		+= machine_kexec.o crash.o \
+obj-$(CONFIG_KEXEC_CORE)	+= machine_kexec.o crash.o \
 				   machine_kexec_$(BITS).o
 obj-$(CONFIG_AUDIT)		+= audit.o
 obj64-$(CONFIG_AUDIT)		+= compat_audit.o
@@ -128,7 +128,7 @@ obj64-$(CONFIG_PPC_TRANSACTIONAL_MEM)	+= tm.o
 obj-$(CONFIG_PPC64)		+= $(obj64-y)
 obj-$(CONFIG_PPC32)		+= $(obj32-y)
 
-ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),)
+ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC_CORE),)
 obj-y				+= ppc_save_regs.o
 endif
 
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 04c546e20cc0..d3d482b628a6 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -153,7 +153,7 @@ __secondary_hold:
 	cmpdi	0,r12,0
 	beq	100b
 
-#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE)
 #ifdef CONFIG_PPC_BOOK3E
 	tovirt(r12,r12)
 #endif
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S
index 93cf7a5846a6..1863324c6a3c 100644
--- a/arch/powerpc/kernel/misc_32.S
+++ b/arch/powerpc/kernel/misc_32.S
@@ -614,7 +614,7 @@ _GLOBAL(start_secondary_resume)
 _GLOBAL(__main)
 	blr
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	/*
 	 * Must be relocatable PIC code callable as a C function.
 	 */
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
index 4f178671f230..32be2a844947 100644
--- a/arch/powerpc/kernel/misc_64.S
+++ b/arch/powerpc/kernel/misc_64.S
@@ -478,7 +478,7 @@ _GLOBAL(kexec_wait)
 	addi	r5,r5,kexec_flag-1b
 
 99:	HMT_LOW
-#ifdef CONFIG_KEXEC		/* use no memory without kexec */
+#ifdef CONFIG_KEXEC_CORE	/* use no memory without kexec */
 	lwz	r4,0(r5)
 	cmpwi	0,r4,0
 	beq	99b
@@ -503,7 +503,7 @@ kexec_flag:
 	.long	0
 
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 #ifdef CONFIG_PPC_BOOK3E
 /*
  * BOOK3E has no real MMU mode, so we have to setup the initial TLB
@@ -716,4 +716,4 @@ _GLOBAL(kexec_sequence)
 	mtlr	4
 	li	r5,0
 	blr	/* image->start(physid, image->start, 0); */
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index b0245bed6f54..fa7aea479fba 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -427,7 +427,7 @@ static int __init early_init_dt_scan_chosen_ppc(unsigned long node,
 		tce_alloc_end = *lprop;
 #endif
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	lprop = of_get_flat_dt_prop(node, "linux,crashkernel-base", NULL);
 	if (lprop)
 		crashk_res.start = *lprop;
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 7ac8e6eaab5b..c3e129080c31 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -346,7 +346,7 @@ void early_setup_secondary(void)
 
 #endif /* CONFIG_SMP */
 
-#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE)
 static bool use_spinloop(void)
 {
 	if (!IS_ENABLED(CONFIG_PPC_BOOK3E))
@@ -391,7 +391,7 @@ void smp_release_cpus(void)
 
 	DBG(" <- smp_release_cpus()\n");
 }
-#endif /* CONFIG_SMP || CONFIG_KEXEC */
+#endif /* CONFIG_SMP || CONFIG_KEXEC_CORE */
 
 /*
  * Initialize some remaining members of the ppc64_caches and systemcfg
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 9c6f3fd58059..893bd7f79be6 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -193,7 +193,7 @@ int smp_request_message_ipi(int virq, int msg)
 	if (msg < 0 || msg > PPC_MSG_DEBUGGER_BREAK) {
 		return -EINVAL;
 	}
-#if !defined(CONFIG_DEBUGGER) && !defined(CONFIG_KEXEC)
+#if !defined(CONFIG_DEBUGGER) && !defined(CONFIG_KEXEC_CORE)
 	if (msg == PPC_MSG_DEBUGGER_BREAK) {
 		return 1;
 	}
@@ -325,7 +325,7 @@ void tick_broadcast(const struct cpumask *mask)
 }
 #endif
 
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC_CORE)
 void smp_send_debugger_break(void)
 {
 	int cpu;
@@ -340,7 +340,7 @@ void smp_send_debugger_break(void)
 }
 #endif
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *))
 {
 	crash_ipi_function_ptr = crash_ipi_callback;
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 023a462725b5..d26605d950fe 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -65,7 +65,7 @@
 #include <asm/hmi.h>
 #include <sysdev/fsl_pci.h>
 
-#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC_CORE)
 int (*__debugger)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_ipi)(struct pt_regs *regs) __read_mostly;
 int (*__debugger_bpt)(struct pt_regs *regs) __read_mostly;
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
index 1179115a4b5c..3803b0addf65 100644
--- a/arch/powerpc/platforms/85xx/corenet_generic.c
+++ b/arch/powerpc/platforms/85xx/corenet_generic.c
@@ -220,7 +220,7 @@ define_machine(corenet_generic) {
  *
  * Likewise, problems have been seen with kexec when coreint is enabled.
  */
-#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC_CORE)
 	.get_irq		= mpic_get_irq,
 #else
 	.get_irq		= mpic_get_coreint_irq,
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index fe9f19e5e935..a83a6d26090d 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -349,13 +349,13 @@ struct smp_ops_t smp_85xx_ops = {
 	.cpu_disable	= generic_cpu_disable,
 	.cpu_die	= generic_cpu_die,
 #endif
-#if defined(CONFIG_KEXEC) && !defined(CONFIG_PPC64)
+#if defined(CONFIG_KEXEC_CORE) && !defined(CONFIG_PPC64)
 	.give_timebase	= smp_generic_give_timebase,
 	.take_timebase	= smp_generic_take_timebase,
 #endif
 };
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 #ifdef CONFIG_PPC32
 atomic_t kexec_down_cpus = ATOMIC_INIT(0);
 
@@ -458,7 +458,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image)
 
 	default_machine_kexec(image);
 }
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
 
 static void smp_85xx_basic_setup(int cpu_nr)
 {
@@ -512,7 +512,7 @@ void __init mpc85xx_smp_init(void)
 #endif
 	smp_ops = &smp_85xx_ops;
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	ppc_md.kexec_cpu_down = mpc85xx_smp_kexec_cpu_down;
 	ppc_md.machine_kexec = mpc85xx_smp_machine_kexec;
 #endif
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index e84d8fbc2e21..96c2b8a40630 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -676,7 +676,7 @@ static ssize_t spu_stat_show(struct device *dev,
 
 static DEVICE_ATTR(stat, 0444, spu_stat_show, NULL);
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 
 struct crash_spu_info {
 	struct spu *spu;
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index efe8b6bb168b..d50c7d99baaf 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -174,7 +174,7 @@ static void pnv_shutdown(void)
 	opal_shutdown();
 }
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 static void pnv_kexec_wait_secondaries_down(void)
 {
 	int my_cpu, i, notified = -1;
@@ -245,7 +245,7 @@ static void pnv_kexec_cpu_down(int crash_shutdown, int secondary)
 		opal_reinit_cpus(OPAL_REINIT_CPUS_HILE_BE);
 	}
 }
-#endif /* CONFIG_KEXEC */
+#endif /* CONFIG_KEXEC_CORE */
 
 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
 static unsigned long pnv_memory_block_size(void)
@@ -311,7 +311,7 @@ define_machine(powernv) {
 	.machine_shutdown	= pnv_shutdown,
 	.power_save             = NULL,
 	.calibrate_decr		= generic_calibrate_decr,
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	.kexec_cpu_down		= pnv_kexec_cpu_down,
 #endif
 #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 3a487e7f4a5e..6244bc849469 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -250,7 +250,7 @@ static int __init ps3_probe(void)
 	return 1;
 }
 
-#if defined(CONFIG_KEXEC)
+#if defined(CONFIG_KEXEC_CORE)
 static void ps3_kexec_cpu_down(int crash_shutdown, int secondary)
 {
 	int cpu = smp_processor_id();
@@ -276,7 +276,7 @@ define_machine(ps3) {
 	.progress			= ps3_progress,
 	.restart			= ps3_restart,
 	.halt				= ps3_halt,
-#if defined(CONFIG_KEXEC)
+#if defined(CONFIG_KEXEC_CORE)
 	.kexec_cpu_down			= ps3_kexec_cpu_down,
 #endif
 };
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile
index fedc2ccf029d..dd9d9c2ba71b 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -8,7 +8,7 @@ obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
 			   pci.o pci_dlpar.o eeh_pseries.o msi.o
 obj-$(CONFIG_SMP)	+= smp.o
 obj-$(CONFIG_SCANLOG)	+= scanlog.o
-obj-$(CONFIG_KEXEC)	+= kexec.o
+obj-$(CONFIG_KEXEC_CORE)	+= kexec.o
 obj-$(CONFIG_PSERIES_ENERGY)	+= pseries_energy.o
 
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug-cpu.o
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 97aa3f332f24..7736352f7279 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -367,7 +367,7 @@ void pseries_disable_reloc_on_exc(void)
 }
 EXPORT_SYMBOL(pseries_disable_reloc_on_exc);
 
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 static void pSeries_machine_kexec(struct kimage *image)
 {
 	if (firmware_has_feature(FW_FEATURE_SET_MODE))
@@ -725,7 +725,7 @@ define_machine(pseries) {
 	.progress		= rtas_progress,
 	.system_reset_exception = pSeries_system_reset_exception,
 	.machine_check_exception = pSeries_machine_check_exception,
-#ifdef CONFIG_KEXEC
+#ifdef CONFIG_KEXEC_CORE
 	.machine_kexec          = pSeries_machine_kexec,
 	.kexec_cpu_down         = pseries_kexec_cpu_down,
 #endif
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:40:12 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:40:12 -0200
Subject: [PATCH v9 05/10] powerpc: Factor out relocation code in module_64.c
In-Reply-To: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017617-8540-6-git-send-email-bauerman@linux.vnet.ibm.com>

The kexec_file_load system call needs to relocate the purgatory, so
factor out the module relocation code so that it can be shared.

This patch's purpose is to move the ELF relocation logic from
apply_relocate_add to the new function elf64_apply_relocate_add_item
with as few changes as possible. The following changes were needed:

elf64_apply_relocate_add_item takes a my_r2 argument because the kexec
code can't use the my_r2 function since it doesn't have a struct module
to pass to it. For the same reason, it also takes an obj_name argument to
use in error messages. It still takes a pointer to struct module argument,
but kexec code can just pass NULL because except for the TOC symbol, the
purgatory doesn't have undefined symbols so the module pointer isn't used.

Apart from what is described in the paragraph above, the code has no
functional changes.

Suggested-by: Michael Ellerman <mpe at ellerman.id.au>
Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
---
 arch/powerpc/kernel/module_64.c | 344 +++++++++++++++++++++-------------------
 1 file changed, 182 insertions(+), 162 deletions(-)

diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 183368e008cf..61baad036639 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -507,6 +507,181 @@ static int restore_r2(u32 *instruction, struct module *me)
 	return 1;
 }
 
+static int elf64_apply_relocate_add_item(const Elf64_Shdr *sechdrs,
+					 const char *strtab,
+					 const Elf64_Rela *rela,
+					 const Elf64_Sym *sym,
+					 unsigned long *location,
+					 unsigned long value,
+					 unsigned long my_r2,
+					 const char *obj_name,
+					 struct module *me)
+{
+	switch (ELF64_R_TYPE(rela->r_info)) {
+	case R_PPC64_ADDR32:
+		/* Simply set it */
+		*(u32 *)location = value;
+		break;
+
+	case R_PPC64_ADDR64:
+		/* Simply set it */
+		*(unsigned long *)location = value;
+		break;
+
+	case R_PPC64_TOC:
+		*(unsigned long *)location = my_r2;
+		break;
+
+	case R_PPC64_TOC16:
+		/* Subtract TOC pointer */
+		value -= my_r2;
+		if (value + 0x8000 > 0xffff) {
+			pr_err("%s: bad TOC16 relocation (0x%lx)\n",
+			       obj_name, value);
+			return -ENOEXEC;
+		}
+		*((uint16_t *) location)
+			= (*((uint16_t *) location) & ~0xffff)
+			| (value & 0xffff);
+		break;
+
+	case R_PPC64_TOC16_LO:
+		/* Subtract TOC pointer */
+		value -= my_r2;
+		*((uint16_t *) location)
+			= (*((uint16_t *) location) & ~0xffff)
+			| (value & 0xffff);
+		break;
+
+	case R_PPC64_TOC16_DS:
+		/* Subtract TOC pointer */
+		value -= my_r2;
+		if ((value & 3) != 0 || value + 0x8000 > 0xffff) {
+			pr_err("%s: bad TOC16_DS relocation (0x%lx)\n",
+			       obj_name, value);
+			return -ENOEXEC;
+		}
+		*((uint16_t *) location)
+			= (*((uint16_t *) location) & ~0xfffc)
+			| (value & 0xfffc);
+		break;
+
+	case R_PPC64_TOC16_LO_DS:
+		/* Subtract TOC pointer */
+		value -= my_r2;
+		if ((value & 3) != 0) {
+			pr_err("%s: bad TOC16_LO_DS relocation (0x%lx)\n",
+			       obj_name, value);
+			return -ENOEXEC;
+		}
+		*((uint16_t *) location)
+			= (*((uint16_t *) location) & ~0xfffc)
+			| (value & 0xfffc);
+		break;
+
+	case R_PPC64_TOC16_HA:
+		/* Subtract TOC pointer */
+		value -= my_r2;
+		value = ((value + 0x8000) >> 16);
+		*((uint16_t *) location)
+			= (*((uint16_t *) location) & ~0xffff)
+			| (value & 0xffff);
+		break;
+
+	case R_PPC_REL24:
+		/* FIXME: Handle weak symbols here --RR */
+		if (sym->st_shndx == SHN_UNDEF) {
+			/* External: go via stub */
+			value = stub_for_addr(sechdrs, value, me);
+			if (!value)
+				return -ENOENT;
+			if (!restore_r2((u32 *)location + 1, me))
+				return -ENOEXEC;
+
+			squash_toc_save_inst(strtab + sym->st_name, value);
+		} else
+			value += local_entry_offset(sym);
+
+		/* Convert value to relative */
+		value -= (unsigned long)location;
+		if (value + 0x2000000 > 0x3ffffff || (value & 3) != 0) {
+			pr_err("%s: REL24 %li out of range!\n",
+			       obj_name, (long int)value);
+			return -ENOEXEC;
+		}
+
+		/* Only replace bits 2 through 26 */
+		*(uint32_t *)location
+			= (*(uint32_t *)location & ~0x03fffffc)
+			| (value & 0x03fffffc);
+		break;
+
+	case R_PPC64_REL64:
+		/* 64 bits relative (used by features fixups) */
+		*location = value - (unsigned long)location;
+		break;
+
+	case R_PPC64_TOCSAVE:
+		/*
+		 * Marker reloc indicates we don't have to save r2.
+		 * That would only save us one instruction, so ignore
+		 * it.
+		 */
+		break;
+
+	case R_PPC64_ENTRY:
+		/*
+		 * Optimize ELFv2 large code model entry point if
+		 * the TOC is within 2GB range of current location.
+		 */
+		value = my_r2 - (unsigned long)location;
+		if (value + 0x80008000 > 0xffffffff)
+			break;
+		/*
+		 * Check for the large code model prolog sequence:
+		 *	ld r2, ...(r12)
+		 *	add r2, r2, r12
+		 */
+		if ((((uint32_t *)location)[0] & ~0xfffc)
+		    != 0xe84c0000)
+			break;
+		if (((uint32_t *)location)[1] != 0x7c426214)
+			break;
+		/*
+		 * If found, replace it with:
+		 *	addis r2, r12, (.TOC.-func)@ha
+		 *	addi r2, r12, (.TOC.-func)@l
+		 */
+		((uint32_t *)location)[0] = 0x3c4c0000 + PPC_HA(value);
+		((uint32_t *)location)[1] = 0x38420000 + PPC_LO(value);
+		break;
+
+	case R_PPC64_REL16_HA:
+		/* Subtract location pointer */
+		value -= (unsigned long)location;
+		value = ((value + 0x8000) >> 16);
+		*((uint16_t *) location)
+			= (*((uint16_t *) location) & ~0xffff)
+			| (value & 0xffff);
+		break;
+
+	case R_PPC64_REL16_LO:
+		/* Subtract location pointer */
+		value -= (unsigned long)location;
+		*((uint16_t *) location)
+			= (*((uint16_t *) location) & ~0xffff)
+			| (value & 0xffff);
+		break;
+
+	default:
+		pr_err("%s: Unknown ADD relocation: %lu\n", obj_name,
+		       (unsigned long)ELF64_R_TYPE(rela->r_info));
+		return -ENOEXEC;
+	}
+
+	return 0;
+}
+
 int apply_relocate_add(Elf64_Shdr *sechdrs,
 		       const char *strtab,
 		       unsigned int symindex,
@@ -514,6 +689,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
 		       struct module *me)
 {
 	unsigned int i;
+	int ret;
 	Elf64_Rela *rela = (void *)sechdrs[relsec].sh_addr;
 	Elf64_Sym *sym;
 	unsigned long *location;
@@ -548,168 +724,12 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
 		/* `Everything is relative'. */
 		value = sym->st_value + rela[i].r_addend;
 
-		switch (ELF64_R_TYPE(rela[i].r_info)) {
-		case R_PPC64_ADDR32:
-			/* Simply set it */
-			*(u32 *)location = value;
-			break;
-
-		case R_PPC64_ADDR64:
-			/* Simply set it */
-			*(unsigned long *)location = value;
-			break;
-
-		case R_PPC64_TOC:
-			*(unsigned long *)location = my_r2(sechdrs, me);
-			break;
-
-		case R_PPC64_TOC16:
-			/* Subtract TOC pointer */
-			value -= my_r2(sechdrs, me);
-			if (value + 0x8000 > 0xffff) {
-				pr_err("%s: bad TOC16 relocation (0x%lx)\n",
-				       me->name, value);
-				return -ENOEXEC;
-			}
-			*((uint16_t *) location)
-				= (*((uint16_t *) location) & ~0xffff)
-				| (value & 0xffff);
-			break;
-
-		case R_PPC64_TOC16_LO:
-			/* Subtract TOC pointer */
-			value -= my_r2(sechdrs, me);
-			*((uint16_t *) location)
-				= (*((uint16_t *) location) & ~0xffff)
-				| (value & 0xffff);
-			break;
-
-		case R_PPC64_TOC16_DS:
-			/* Subtract TOC pointer */
-			value -= my_r2(sechdrs, me);
-			if ((value & 3) != 0 || value + 0x8000 > 0xffff) {
-				pr_err("%s: bad TOC16_DS relocation (0x%lx)\n",
-				       me->name, value);
-				return -ENOEXEC;
-			}
-			*((uint16_t *) location)
-				= (*((uint16_t *) location) & ~0xfffc)
-				| (value & 0xfffc);
-			break;
-
-		case R_PPC64_TOC16_LO_DS:
-			/* Subtract TOC pointer */
-			value -= my_r2(sechdrs, me);
-			if ((value & 3) != 0) {
-				pr_err("%s: bad TOC16_LO_DS relocation (0x%lx)\n",
-				       me->name, value);
-				return -ENOEXEC;
-			}
-			*((uint16_t *) location)
-				= (*((uint16_t *) location) & ~0xfffc)
-				| (value & 0xfffc);
-			break;
-
-		case R_PPC64_TOC16_HA:
-			/* Subtract TOC pointer */
-			value -= my_r2(sechdrs, me);
-			value = ((value + 0x8000) >> 16);
-			*((uint16_t *) location)
-				= (*((uint16_t *) location) & ~0xffff)
-				| (value & 0xffff);
-			break;
-
-		case R_PPC_REL24:
-			/* FIXME: Handle weak symbols here --RR */
-			if (sym->st_shndx == SHN_UNDEF) {
-				/* External: go via stub */
-				value = stub_for_addr(sechdrs, value, me);
-				if (!value)
-					return -ENOENT;
-				if (!restore_r2((u32 *)location + 1, me))
-					return -ENOEXEC;
-
-				squash_toc_save_inst(strtab + sym->st_name, value);
-			} else
-				value += local_entry_offset(sym);
-
-			/* Convert value to relative */
-			value -= (unsigned long)location;
-			if (value + 0x2000000 > 0x3ffffff || (value & 3) != 0){
-				pr_err("%s: REL24 %li out of range!\n",
-				       me->name, (long int)value);
-				return -ENOEXEC;
-			}
-
-			/* Only replace bits 2 through 26 */
-			*(uint32_t *)location
-				= (*(uint32_t *)location & ~0x03fffffc)
-				| (value & 0x03fffffc);
-			break;
-
-		case R_PPC64_REL64:
-			/* 64 bits relative (used by features fixups) */
-			*location = value - (unsigned long)location;
-			break;
-
-		case R_PPC64_TOCSAVE:
-			/*
-			 * Marker reloc indicates we don't have to save r2.
-			 * That would only save us one instruction, so ignore
-			 * it.
-			 */
-			break;
-
-		case R_PPC64_ENTRY:
-			/*
-			 * Optimize ELFv2 large code model entry point if
-			 * the TOC is within 2GB range of current location.
-			 */
-			value = my_r2(sechdrs, me) - (unsigned long)location;
-			if (value + 0x80008000 > 0xffffffff)
-				break;
-			/*
-			 * Check for the large code model prolog sequence:
-		         *	ld r2, ...(r12)
-			 *	add r2, r2, r12
-			 */
-			if ((((uint32_t *)location)[0] & ~0xfffc)
-			    != 0xe84c0000)
-				break;
-			if (((uint32_t *)location)[1] != 0x7c426214)
-				break;
-			/*
-			 * If found, replace it with:
-			 *	addis r2, r12, (.TOC.-func)@ha
-			 *	addi r2, r12, (.TOC.-func)@l
-			 */
-			((uint32_t *)location)[0] = 0x3c4c0000 + PPC_HA(value);
-			((uint32_t *)location)[1] = 0x38420000 + PPC_LO(value);
-			break;
-
-		case R_PPC64_REL16_HA:
-			/* Subtract location pointer */
-			value -= (unsigned long)location;
-			value = ((value + 0x8000) >> 16);
-			*((uint16_t *) location)
-				= (*((uint16_t *) location) & ~0xffff)
-				| (value & 0xffff);
-			break;
-
-		case R_PPC64_REL16_LO:
-			/* Subtract location pointer */
-			value -= (unsigned long)location;
-			*((uint16_t *) location)
-				= (*((uint16_t *) location) & ~0xffff)
-				| (value & 0xffff);
-			break;
-
-		default:
-			pr_err("%s: Unknown ADD relocation: %lu\n",
-			       me->name,
-			       (unsigned long)ELF64_R_TYPE(rela[i].r_info));
-			return -ENOEXEC;
-		}
+		ret = elf64_apply_relocate_add_item(sechdrs, strtab, &rela[i],
+						    sym, location, value,
+						    my_r2(sechdrs, me),
+						    me->name, me);
+		if (ret)
+			return ret;
 	}
 
 	return 0;
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:40:14 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:40:14 -0200
Subject: [PATCH v9 07/10] powerpc: Add functions to read ELF files of any
 endianness.
In-Reply-To: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017617-8540-8-git-send-email-bauerman@linux.vnet.ibm.com>

A little endian kernel might need to kexec a big endian kernel (the
opposite is less likely but could happen as well), so we can't just cast
the buffer with the binary to ELF structs and use them as is done
elsewhere.

This patch adds functions which do byte-swapping as necessary when
populating the ELF structs. These functions will be used in the next
patch in the series.

Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/elf_util.h |  21 ++
 arch/powerpc/kernel/elf_util.c      | 418 ++++++++++++++++++++++++++++++++++++
 2 files changed, 439 insertions(+)

diff --git a/arch/powerpc/include/asm/elf_util.h b/arch/powerpc/include/asm/elf_util.h
index 1df232f65ec8..3dbad8cc7179 100644
--- a/arch/powerpc/include/asm/elf_util.h
+++ b/arch/powerpc/include/asm/elf_util.h
@@ -19,6 +19,18 @@
 
 #include <linux/elf.h>
 
+struct elf_info {
+	/*
+	 * Where the ELF binary contents are kept.
+	 * Memory managed by the user of the struct.
+	 */
+	const char *buffer;
+
+	const struct elfhdr *ehdr;
+	const struct elf_phdr *proghdrs;
+	struct elf_shdr *sechdrs;
+};
+
 /*
  * r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
  * gives the value maximum span in an instruction which uses a signed
@@ -40,4 +52,13 @@ int elf64_apply_relocate_add_item(const Elf64_Shdr *sechdrs, const char *strtab,
 				  unsigned long my_r2, const char *obj_name,
 				  struct module *me);
 
+static inline bool elf_is_elf_file(const struct elfhdr *ehdr)
+{
+	return memcmp(ehdr->e_ident, ELFMAG, SELFMAG) == 0;
+}
+
+int elf_read_from_buffer(const char *buf, size_t len, struct elfhdr *ehdr,
+			 struct elf_info *elf_info);
+void elf_free_info(struct elf_info *elf_info);
+
 #endif /* _ASM_POWERPC_ELF_UTIL_H */
diff --git a/arch/powerpc/kernel/elf_util.c b/arch/powerpc/kernel/elf_util.c
index ffa68cd6fb99..e57e7397f65c 100644
--- a/arch/powerpc/kernel/elf_util.c
+++ b/arch/powerpc/kernel/elf_util.c
@@ -16,7 +16,24 @@
  * GNU General Public License for more details.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/slab.h>
 #include <asm/elf_util.h>
+#include <asm-generic/module.h>
+
+#if ELF_CLASS == ELFCLASS32
+#define elf_addr_to_cpu	elf32_to_cpu
+
+#ifndef Elf_Rel
+#define Elf_Rel		Elf32_Rel
+#endif /* Elf_Rel */
+#else /* ELF_CLASS == ELFCLASS32 */
+#define elf_addr_to_cpu	elf64_to_cpu
+
+#ifndef Elf_Rel
+#define Elf_Rel		Elf64_Rel
+#endif /* Elf_Rel */
 
 /**
  * elf_toc_section - find the toc section in the file with the given ELF headers
@@ -44,3 +61,404 @@ unsigned int elf_toc_section(const struct elfhdr *ehdr,
 
 	return 0;
 }
+
+static uint64_t elf64_to_cpu(const struct elfhdr *ehdr, uint64_t value)
+{
+	if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
+		value = le64_to_cpu(value);
+	else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+		value = be64_to_cpu(value);
+
+	return value;
+}
+#endif /* ELF_CLASS == ELFCLASS32 */
+
+static uint16_t elf16_to_cpu(const struct elfhdr *ehdr, uint16_t value)
+{
+	if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
+		value = le16_to_cpu(value);
+	else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+		value = be16_to_cpu(value);
+
+	return value;
+}
+
+static uint32_t elf32_to_cpu(const struct elfhdr *ehdr, uint32_t value)
+{
+	if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB)
+		value = le32_to_cpu(value);
+	else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+		value = be32_to_cpu(value);
+
+	return value;
+}
+
+/**
+ * elf_is_ehdr_sane - check that it is safe to use the ELF header
+ * @buf_len:	size of the buffer in which the ELF file is loaded.
+ */
+static bool elf_is_ehdr_sane(const struct elfhdr *ehdr, size_t buf_len)
+{
+	if (ehdr->e_phnum > 0 && ehdr->e_phentsize != sizeof(struct elf_phdr)) {
+		pr_debug("Bad program header size.\n");
+		return false;
+	} else if (ehdr->e_shnum > 0 &&
+		   ehdr->e_shentsize != sizeof(struct elf_shdr)) {
+		pr_debug("Bad section header size.\n");
+		return false;
+	} else if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
+		   ehdr->e_version != EV_CURRENT) {
+		pr_debug("Unknown ELF version.\n");
+		return false;
+	}
+
+	if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
+		size_t phdr_size;
+
+		/*
+		 * e_phnum is at most 65535 so calculating the size of the
+		 * program header cannot overflow.
+		 */
+		phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
+
+		/* Sanity check the program header table location. */
+		if (ehdr->e_phoff + phdr_size < ehdr->e_phoff) {
+			pr_debug("Program headers at invalid location.\n");
+			return false;
+		} else if (ehdr->e_phoff + phdr_size > buf_len) {
+			pr_debug("Program headers truncated.\n");
+			return false;
+		}
+	}
+
+	if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) {
+		size_t shdr_size;
+
+		/*
+		 * e_shnum is at most 65536 so calculating
+		 * the size of the section header cannot overflow.
+		 */
+		shdr_size = sizeof(struct elf_shdr) * ehdr->e_shnum;
+
+		/* Sanity check the section header table location. */
+		if (ehdr->e_shoff + shdr_size < ehdr->e_shoff) {
+			pr_debug("Section headers at invalid location.\n");
+			return false;
+		} else if (ehdr->e_shoff + shdr_size > buf_len) {
+			pr_debug("Section headers truncated.\n");
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static int elf_read_ehdr(const char *buf, size_t len, struct elfhdr *ehdr)
+{
+	struct elfhdr *buf_ehdr;
+
+	if (len < sizeof(*buf_ehdr)) {
+		pr_debug("Buffer is too small to hold ELF header.\n");
+		return -ENOEXEC;
+	}
+
+	memset(ehdr, 0, sizeof(*ehdr));
+	memcpy(ehdr->e_ident, buf, sizeof(ehdr->e_ident));
+	if (!elf_is_elf_file(ehdr)) {
+		pr_debug("No ELF header magic.\n");
+		return -ENOEXEC;
+	}
+
+	if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) {
+		pr_debug("Not a supported ELF class.\n");
+		return -1;
+	} else  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB &&
+		ehdr->e_ident[EI_DATA] != ELFDATA2MSB) {
+		pr_debug("Not a supported ELF data format.\n");
+		return -ENOEXEC;
+	}
+
+	buf_ehdr = (struct elfhdr *) buf;
+	if (elf16_to_cpu(ehdr, buf_ehdr->e_ehsize) != sizeof(*buf_ehdr)) {
+		pr_debug("Bad ELF header size.\n");
+		return -ENOEXEC;
+	}
+
+	ehdr->e_type      = elf16_to_cpu(ehdr, buf_ehdr->e_type);
+	ehdr->e_machine   = elf16_to_cpu(ehdr, buf_ehdr->e_machine);
+	ehdr->e_version   = elf32_to_cpu(ehdr, buf_ehdr->e_version);
+	ehdr->e_entry     = elf_addr_to_cpu(ehdr, buf_ehdr->e_entry);
+	ehdr->e_phoff     = elf_addr_to_cpu(ehdr, buf_ehdr->e_phoff);
+	ehdr->e_shoff     = elf_addr_to_cpu(ehdr, buf_ehdr->e_shoff);
+	ehdr->e_flags     = elf32_to_cpu(ehdr, buf_ehdr->e_flags);
+	ehdr->e_phentsize = elf16_to_cpu(ehdr, buf_ehdr->e_phentsize);
+	ehdr->e_phnum     = elf16_to_cpu(ehdr, buf_ehdr->e_phnum);
+	ehdr->e_shentsize = elf16_to_cpu(ehdr, buf_ehdr->e_shentsize);
+	ehdr->e_shnum     = elf16_to_cpu(ehdr, buf_ehdr->e_shnum);
+	ehdr->e_shstrndx  = elf16_to_cpu(ehdr, buf_ehdr->e_shstrndx);
+
+	return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC;
+}
+
+/**
+ * elf_is_phdr_sane - check that it is safe to use the program header
+ * @buf_len:	size of the buffer in which the ELF file is loaded.
+ */
+static bool elf_is_phdr_sane(const struct elf_phdr *phdr, size_t buf_len)
+{
+
+	if (phdr->p_offset + phdr->p_filesz < phdr->p_offset) {
+		pr_debug("ELF segment location wraps around.\n");
+		return false;
+	} else if (phdr->p_offset + phdr->p_filesz > buf_len) {
+		pr_debug("ELF segment not in file.\n");
+		return false;
+	} else if (phdr->p_paddr + phdr->p_memsz < phdr->p_paddr) {
+		pr_debug("ELF segment address wraps around.\n");
+		return false;
+	}
+
+	return true;
+}
+
+static int elf_read_phdr(const char *buf, size_t len, struct elf_info *elf_info,
+			 int idx)
+{
+	/* Override the const in proghdrs, we are the ones doing the loading. */
+	struct elf_phdr *phdr = (struct elf_phdr *) &elf_info->proghdrs[idx];
+	const char *pbuf;
+	struct elf_phdr *buf_phdr;
+
+	pbuf = buf + elf_info->ehdr->e_phoff + (idx * sizeof(*buf_phdr));
+	buf_phdr = (struct elf_phdr *) pbuf;
+
+	phdr->p_type   = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_type);
+	phdr->p_offset = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_offset);
+	phdr->p_paddr  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_paddr);
+	phdr->p_vaddr  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_vaddr);
+	phdr->p_flags  = elf32_to_cpu(elf_info->ehdr, buf_phdr->p_flags);
+
+	/*
+	 * The following fields have a type equivalent to Elf_Addr
+	 * both in 32 bit and 64 bit ELF.
+	 */
+	phdr->p_filesz = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_filesz);
+	phdr->p_memsz  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_memsz);
+	phdr->p_align  = elf_addr_to_cpu(elf_info->ehdr, buf_phdr->p_align);
+
+	return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC;
+}
+
+/**
+ * elf_read_phdrs - read the program headers from the buffer
+ *
+ * This function assumes that the program header table was checked for sanity.
+ * Use elf_is_ehdr_sane() if it wasn't.
+ */
+static int elf_read_phdrs(const char *buf, size_t len,
+			  struct elf_info *elf_info)
+{
+	size_t phdr_size, i;
+	const struct elfhdr *ehdr = elf_info->ehdr;
+
+	/*
+	 * e_phnum is at most 65535 so calculating the size of the
+	 * program header cannot overflow.
+	 */
+	phdr_size = sizeof(struct elf_phdr) * ehdr->e_phnum;
+
+	elf_info->proghdrs = kzalloc(phdr_size, GFP_KERNEL);
+	if (!elf_info->proghdrs)
+		return -ENOMEM;
+
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		int ret;
+
+		ret = elf_read_phdr(buf, len, elf_info, i);
+		if (ret) {
+			kfree(elf_info->proghdrs);
+			elf_info->proghdrs = NULL;
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * elf_is_shdr_sane - check that it is safe to use the section header
+ * @buf_len:	size of the buffer in which the ELF file is loaded.
+ */
+static bool elf_is_shdr_sane(const struct elf_shdr *shdr, size_t buf_len)
+{
+	bool size_ok;
+
+	/* SHT_NULL headers have undefined values, so we can't check them. */
+	if (shdr->sh_type == SHT_NULL)
+		return true;
+
+	/* Now verify sh_entsize */
+	switch (shdr->sh_type) {
+	case SHT_SYMTAB:
+		size_ok = shdr->sh_entsize == sizeof(Elf_Sym);
+		break;
+	case SHT_RELA:
+		size_ok = shdr->sh_entsize == sizeof(Elf_Rela);
+		break;
+	case SHT_DYNAMIC:
+		size_ok = shdr->sh_entsize == sizeof(Elf_Dyn);
+		break;
+	case SHT_REL:
+		size_ok = shdr->sh_entsize == sizeof(Elf_Rel);
+		break;
+	case SHT_NOTE:
+	case SHT_PROGBITS:
+	case SHT_HASH:
+	case SHT_NOBITS:
+	default:
+		/*
+		 * This is a section whose entsize requirements
+		 * I don't care about.  If I don't know about
+		 * the section I can't care about it's entsize
+		 * requirements.
+		 */
+		size_ok = true;
+		break;
+	}
+
+	if (!size_ok) {
+		pr_debug("ELF section with wrong entry size.\n");
+		return false;
+	} else if (shdr->sh_addr + shdr->sh_size < shdr->sh_addr) {
+		pr_debug("ELF section address wraps around.\n");
+		return false;
+	}
+
+	if (shdr->sh_type != SHT_NOBITS) {
+		if (shdr->sh_offset + shdr->sh_size < shdr->sh_offset) {
+			pr_debug("ELF section location wraps around.\n");
+			return false;
+		} else if (shdr->sh_offset + shdr->sh_size > buf_len) {
+			pr_debug("ELF section not in file.\n");
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static int elf_read_shdr(const char *buf, size_t len, struct elf_info *elf_info,
+			 int idx)
+{
+	struct elf_shdr *shdr = &elf_info->sechdrs[idx];
+	const struct elfhdr *ehdr = elf_info->ehdr;
+	const char *sbuf;
+	struct elf_shdr *buf_shdr;
+
+	sbuf = buf + ehdr->e_shoff + idx * sizeof(*buf_shdr);
+	buf_shdr = (struct elf_shdr *) sbuf;
+
+	shdr->sh_name      = elf32_to_cpu(ehdr, buf_shdr->sh_name);
+	shdr->sh_type      = elf32_to_cpu(ehdr, buf_shdr->sh_type);
+	shdr->sh_addr      = elf_addr_to_cpu(ehdr, buf_shdr->sh_addr);
+	shdr->sh_offset    = elf_addr_to_cpu(ehdr, buf_shdr->sh_offset);
+	shdr->sh_link      = elf32_to_cpu(ehdr, buf_shdr->sh_link);
+	shdr->sh_info      = elf32_to_cpu(ehdr, buf_shdr->sh_info);
+
+	/*
+	 * The following fields have a type equivalent to Elf_Addr
+	 * both in 32 bit and 64 bit ELF.
+	 */
+	shdr->sh_flags     = elf_addr_to_cpu(ehdr, buf_shdr->sh_flags);
+	shdr->sh_size      = elf_addr_to_cpu(ehdr, buf_shdr->sh_size);
+	shdr->sh_addralign = elf_addr_to_cpu(ehdr, buf_shdr->sh_addralign);
+	shdr->sh_entsize   = elf_addr_to_cpu(ehdr, buf_shdr->sh_entsize);
+
+	return elf_is_shdr_sane(shdr, len) ? 0 : -ENOEXEC;
+}
+
+/**
+ * elf_read_shdrs - read the section headers from the buffer
+ *
+ * This function assumes that the section header table was checked for sanity.
+ * Use elf_is_ehdr_sane() if it wasn't.
+ */
+static int elf_read_shdrs(const char *buf, size_t len,
+			  struct elf_info *elf_info)
+{
+	size_t shdr_size, i;
+
+	/*
+	 * e_shnum is at most 65536 so calculating
+	 * the size of the section header cannot overflow.
+	 */
+	shdr_size = sizeof(struct elf_shdr) * elf_info->ehdr->e_shnum;
+
+	elf_info->sechdrs = kzalloc(shdr_size, GFP_KERNEL);
+	if (!elf_info->sechdrs)
+		return -ENOMEM;
+
+	for (i = 0; i < elf_info->ehdr->e_shnum; i++) {
+		int ret;
+
+		ret = elf_read_shdr(buf, len, elf_info, i);
+		if (ret) {
+			kfree(elf_info->sechdrs);
+			elf_info->sechdrs = NULL;
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * elf_read_from_buffer - read ELF file and sets up ELF header and ELF info
+ * @buf:	Buffer to read ELF file from.
+ * @len:	Size of @buf.
+ * @ehdr:	Pointer to existing struct which will be populated.
+ * @elf_info:	Pointer to existing struct which will be populated.
+ *
+ * This function allows reading ELF files with different byte order than
+ * the kernel, byte-swapping the fields as needed.
+ *
+ * Return:
+ * On success returns 0, and the caller should call elf_free_info(elf_info) to
+ * free the memory allocated for the section and program headers.
+ */
+int elf_read_from_buffer(const char *buf, size_t len, struct elfhdr *ehdr,
+			 struct elf_info *elf_info)
+{
+	int ret;
+
+	ret = elf_read_ehdr(buf, len, ehdr);
+	if (ret)
+		return ret;
+
+	elf_info->buffer = buf;
+	elf_info->ehdr = ehdr;
+	if (ehdr->e_phoff > 0 && ehdr->e_phnum > 0) {
+		ret = elf_read_phdrs(buf, len, elf_info);
+		if (ret)
+			return ret;
+	}
+	if (ehdr->e_shoff > 0 && ehdr->e_shnum > 0) {
+		ret = elf_read_shdrs(buf, len, elf_info);
+		if (ret) {
+			kfree(elf_info->proghdrs);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * elf_free_info - free memory allocated by elf_read_from_buffer
+ */
+void elf_free_info(struct elf_info *elf_info)
+{
+	kfree(elf_info->proghdrs);
+	kfree(elf_info->sechdrs);
+	memset(elf_info, 0, sizeof(*elf_info));
+}
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:40:15 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:40:15 -0200
Subject: [PATCH v9 08/10] powerpc: Add support for loading ELF kernels with
 kexec_file_load.
In-Reply-To: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017617-8540-9-git-send-email-bauerman@linux.vnet.ibm.com>

This uses all the infrastructure built up by the previous patches
in the series to load an ELF vmlinux file and an initrd. It uses the
flattened device tree at initial_boot_params as a base and adjusts memory
reservations and its /chosen node for the next kernel.

[akpm at linux-foundation.org: coding-style fixes]
Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
---
 arch/powerpc/include/asm/kexec.h            |  12 +
 arch/powerpc/kernel/Makefile                |   3 +-
 arch/powerpc/kernel/kexec_elf_64.c          | 280 +++++++++++++++++++++++
 arch/powerpc/kernel/machine_kexec_file_64.c | 338 +++++++++++++++++++++++++++-
 4 files changed, 630 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index eca2f975bf44..4497db7555b0 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -91,6 +91,18 @@ static inline bool kdump_in_progress(void)
 	return crashing_cpu >= 0;
 }
 
+#ifdef CONFIG_KEXEC_FILE
+extern struct kexec_file_ops kexec_elf64_ops;
+
+int setup_purgatory(struct kimage *image, const void *slave_code,
+		    const void *fdt, unsigned long kernel_load_addr,
+		    unsigned long fdt_load_addr, unsigned long stack_top,
+		    int debug);
+int setup_new_fdt(void *fdt, unsigned long initrd_load_addr,
+		  unsigned long initrd_len, const char *cmdline);
+bool find_debug_console(const void *fdt);
+#endif /* CONFIG_KEXEC_FILE */
+
 #else /* !CONFIG_KEXEC_CORE */
 static inline void crash_kexec_secondary(struct pt_regs *regs) { }
 
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index de14b7eb11bb..424b13b1b2b0 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -109,7 +109,8 @@ obj-$(CONFIG_PCI)		+= pci_$(BITS).o $(pci64-y) \
 obj-$(CONFIG_PCI_MSI)		+= msi.o
 obj-$(CONFIG_KEXEC_CORE)	+= machine_kexec.o crash.o \
 				   machine_kexec_$(BITS).o
-obj-$(CONFIG_KEXEC_FILE)	+= machine_kexec_file_$(BITS).o elf_util.o
+obj-$(CONFIG_KEXEC_FILE)	+= machine_kexec_file_$(BITS).o elf_util.o \
+				   kexec_elf_$(BITS).o
 obj-$(CONFIG_AUDIT)		+= audit.o
 obj64-$(CONFIG_AUDIT)		+= compat_audit.o
 
diff --git a/arch/powerpc/kernel/kexec_elf_64.c b/arch/powerpc/kernel/kexec_elf_64.c
new file mode 100644
index 000000000000..dc29e0131b76
--- /dev/null
+++ b/arch/powerpc/kernel/kexec_elf_64.c
@@ -0,0 +1,280 @@
+/*
+ * Load ELF vmlinux file for the kexec_file_load syscall.
+ *
+ * Copyright (C) 2004  Adam Litke (agl at us.ibm.com)
+ * Copyright (C) 2004  IBM Corp.
+ * Copyright (C) 2005  R Sharada (sharada at in.ibm.com)
+ * Copyright (C) 2006  Mohan Kumar M (mohan at in.ibm.com)
+ * Copyright (C) 2016  IBM Corporation
+ *
+ * Based on kexec-tools' kexec-elf-exec.c and kexec-elf-ppc64.c.
+ * Heavily modified for the kernel by
+ * Thiago Jung Bauermann <bauerman at linux.vnet.ibm.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.
+ */
+
+#define pr_fmt(fmt)	"kexec_elf: " fmt
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/elf.h>
+#include <linux/kexec.h>
+#include <linux/of_fdt.h>
+#include <linux/libfdt.h>
+#include <asm/elf_util.h>
+
+#define PURGATORY_STACK_SIZE	(16 * 1024)
+
+/**
+ * build_elf_exec_info - read ELF executable and check that we can use it
+ */
+static int build_elf_exec_info(const char *buf, size_t len, struct elfhdr *ehdr,
+			       struct elf_info *elf_info)
+{
+	int i;
+	int ret;
+
+	ret = elf_read_from_buffer(buf, len, ehdr, elf_info);
+	if (ret)
+		return ret;
+
+	/* Big endian vmlinux has type ET_DYN. */
+	if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
+		pr_err("Not an ELF executable.\n");
+		goto error;
+	} else if (!elf_info->proghdrs) {
+		pr_err("No ELF program header.\n");
+		goto error;
+	}
+
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		/*
+		 * Kexec does not support loading interpreters.
+		 * In addition this check keeps us from attempting
+		 * to kexec ordinay executables.
+		 */
+		if (elf_info->proghdrs[i].p_type == PT_INTERP) {
+			pr_err("Requires an ELF interpreter.\n");
+			goto error;
+		}
+	}
+
+	return 0;
+error:
+	elf_free_info(elf_info);
+	return -ENOEXEC;
+}
+
+static int elf64_probe(const char *buf, unsigned long len)
+{
+	struct elfhdr ehdr;
+	struct elf_info elf_info;
+	int ret;
+
+	ret = build_elf_exec_info(buf, len, &ehdr, &elf_info);
+	if (ret)
+		return ret;
+
+	elf_free_info(&elf_info);
+
+	return elf_check_arch(&ehdr) ? 0 : -ENOEXEC;
+}
+
+/**
+ * elf_exec_load - load ELF executable image
+ * @lowest_load_addr:	On return, will be the address where the first PT_LOAD
+ *			section will be loaded in memory.
+ *
+ * Return:
+ * 0 on success, negative value on failure.
+ */
+static int elf_exec_load(struct kimage *image, struct elfhdr *ehdr,
+			 struct elf_info *elf_info,
+			 unsigned long *lowest_load_addr)
+{
+	unsigned long base = 0, lowest_addr = UINT_MAX;
+	int ret;
+	size_t i;
+	struct kexec_buf kbuf = { .image = image, .buf_max = ppc64_rma_size,
+				  .top_down = false };
+
+	/* Read in the PT_LOAD segments. */
+	for (i = 0; i < ehdr->e_phnum; i++) {
+		unsigned long load_addr;
+		size_t size;
+		const struct elf_phdr *phdr;
+
+		phdr = &elf_info->proghdrs[i];
+		if (phdr->p_type != PT_LOAD)
+			continue;
+
+		size = phdr->p_filesz;
+		if (size > phdr->p_memsz)
+			size = phdr->p_memsz;
+
+		kbuf.buffer = (void *) elf_info->buffer + phdr->p_offset;
+		kbuf.bufsz = size;
+		kbuf.memsz = phdr->p_memsz;
+		kbuf.buf_align = phdr->p_align;
+		kbuf.buf_min = phdr->p_paddr + base;
+		ret = kexec_add_buffer(&kbuf);
+		if (ret)
+			goto out;
+		load_addr = kbuf.mem;
+
+		if (load_addr < lowest_addr)
+			lowest_addr = load_addr;
+	}
+
+	/* Update entry point to reflect new load address. */
+	ehdr->e_entry += base;
+
+	*lowest_load_addr = lowest_addr;
+	ret = 0;
+ out:
+	return ret;
+}
+
+static void *elf64_load(struct kimage *image, char *kernel_buf,
+			unsigned long kernel_len, char *initrd,
+			unsigned long initrd_len, char *cmdline,
+			unsigned long cmdline_len)
+{
+	int i, ret;
+	unsigned int fdt_size;
+	unsigned long kernel_load_addr, purgatory_load_addr;
+	unsigned long initrd_load_addr = 0, fdt_load_addr, stack_top;
+	void *fdt;
+	const void *slave_code;
+	struct elfhdr ehdr;
+	struct elf_info elf_info;
+	struct fdt_reserve_entry *rsvmap;
+	struct kexec_buf kbuf = { .image = image, .buf_min = 0,
+				  .buf_max = ppc64_rma_size };
+
+	ret = build_elf_exec_info(kernel_buf, kernel_len, &ehdr, &elf_info);
+	if (ret)
+		goto out;
+
+	ret = elf_exec_load(image, &ehdr, &elf_info, &kernel_load_addr);
+	if (ret)
+		goto out;
+
+	pr_debug("Loaded the kernel at 0x%lx\n", kernel_load_addr);
+
+	ret = kexec_load_purgatory(image, 0, ppc64_rma_size, true,
+				   &purgatory_load_addr);
+	if (ret) {
+		pr_err("Loading purgatory failed.\n");
+		goto out;
+	}
+
+	pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr);
+
+	if (initrd != NULL) {
+		kbuf.buffer = initrd;
+		kbuf.bufsz = kbuf.memsz = initrd_len;
+		kbuf.buf_align = PAGE_SIZE;
+		kbuf.top_down = false;
+		ret = kexec_add_buffer(&kbuf);
+		if (ret)
+			goto out;
+		initrd_load_addr = kbuf.mem;
+
+		pr_debug("Loaded initrd at 0x%lx\n", initrd_load_addr);
+	}
+
+	fdt_size = fdt_totalsize(initial_boot_params) * 2;
+	fdt = kmalloc(fdt_size, GFP_KERNEL);
+	if (!fdt) {
+		pr_err("Not enough memory for the device tree.\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+	ret = fdt_open_into(initial_boot_params, fdt, fdt_size);
+	if (ret < 0) {
+		pr_err("Error setting up the new device tree.\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = setup_new_fdt(fdt, initrd_load_addr, initrd_len, cmdline);
+	if (ret)
+		goto out;
+
+	/*
+	 * Documentation/devicetree/booting-without-of.txt says we need to
+	 * add a reservation entry for the device tree block, but
+	 * early_init_fdt_reserve_self reserves the memory even if there's no
+	 * such entry. We'll add a reservation entry anyway, to be safe and
+	 * compliant.
+	 *
+	 * Use dummy values, we will correct them in a moment.
+	 */
+	ret = fdt_add_mem_rsv(fdt, 1, 1);
+	if (ret) {
+		pr_err("Error reserving device tree memory: %s\n",
+		       fdt_strerror(ret));
+		ret = -EINVAL;
+		goto out;
+	}
+	fdt_pack(fdt);
+
+	kbuf.buffer = fdt;
+	kbuf.bufsz = kbuf.memsz = fdt_size;
+	kbuf.buf_align = PAGE_SIZE;
+	kbuf.top_down = true;
+	ret = kexec_add_buffer(&kbuf);
+	if (ret)
+		goto out;
+	fdt_load_addr = kbuf.mem;
+
+	/*
+	 * Fix fdt reservation, now that we now where it will be loaded
+	 * and how big it is.
+	 */
+	rsvmap = fdt + fdt_off_mem_rsvmap(fdt);
+	i = fdt_num_mem_rsv(fdt) - 1;
+	rsvmap[i].address = cpu_to_fdt64(fdt_load_addr);
+	rsvmap[i].size = cpu_to_fdt64(fdt_totalsize(fdt));
+
+	pr_debug("Loaded device tree at 0x%lx\n", fdt_load_addr);
+
+	kbuf.memsz = PURGATORY_STACK_SIZE;
+	kbuf.buf_align = PAGE_SIZE;
+	kbuf.top_down = true;
+	ret = kexec_locate_mem_hole(&kbuf);
+	if (ret) {
+		pr_err("Couldn't find free memory for the purgatory stack.\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+	stack_top = kbuf.mem + PURGATORY_STACK_SIZE - 1;
+	pr_debug("Purgatory stack is at 0x%lx\n", stack_top);
+
+	slave_code = elf_info.buffer + elf_info.proghdrs[0].p_offset;
+	ret = setup_purgatory(image, slave_code, fdt, kernel_load_addr,
+			      fdt_load_addr, stack_top,
+			      find_debug_console(fdt));
+	if (ret)
+		pr_err("Error setting up the purgatory.\n");
+
+out:
+	elf_free_info(&elf_info);
+
+	/* Make kimage_file_post_load_cleanup free the fdt buffer for us. */
+	return ret ? ERR_PTR(ret) : fdt;
+}
+
+struct kexec_file_ops kexec_elf64_ops = {
+	.probe = elf64_probe,
+	.load = elf64_load,
+};
diff --git a/arch/powerpc/kernel/machine_kexec_file_64.c b/arch/powerpc/kernel/machine_kexec_file_64.c
index c6b8f75c1624..9acc56d199f0 100644
--- a/arch/powerpc/kernel/machine_kexec_file_64.c
+++ b/arch/powerpc/kernel/machine_kexec_file_64.c
@@ -3,11 +3,12 @@
  *
  * Copyright (C) 2004  Adam Litke (agl at us.ibm.com)
  * Copyright (C) 2004  IBM Corp.
+ * Copyright (C) 2004,2005  Milton D Miller II, IBM Corporation
  * Copyright (C) 2005  R Sharada (sharada at in.ibm.com)
  * Copyright (C) 2006  Mohan Kumar M (mohan at in.ibm.com)
  * Copyright (C) 2016  IBM Corporation
  *
- * Based on kexec-tools' kexec-elf-ppc64.c.
+ * Based on kexec-tools' kexec-elf-ppc64.c, fs2dt.c.
  * Heavily modified for the kernel by
  * Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>.
  *
@@ -24,12 +25,15 @@
 #include <linux/slab.h>
 #include <linux/kexec.h>
 #include <linux/memblock.h>
+#include <linux/of_fdt.h>
 #include <linux/libfdt.h>
 #include <asm/elf_util.h>
 
 #define SLAVE_CODE_SIZE		256
 
-static struct kexec_file_ops *kexec_file_loaders[] = { };
+static struct kexec_file_ops *kexec_file_loaders[] = {
+	&kexec_elf64_ops,
+};
 
 int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
 				  unsigned long buf_len)
@@ -243,3 +247,333 @@ int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
 
 	return 0;
 }
+
+/**
+ * setup_purgatory - initialize the purgatory's global variables
+ * @image:		kexec image.
+ * @slave_code:		Slave code for the purgatory.
+ * @fdt:		Flattened device tree for the next kernel.
+ * @kernel_load_addr:	Address where the kernel is loaded.
+ * @fdt_load_addr:	Address where the flattened device tree is loaded.
+ * @stack_top:		Address where the purgatory can place its stack.
+ * @debug:		Can the purgatory print messages to the console?
+ *
+ * Return: 0 on success, or negative errno on error.
+ */
+int setup_purgatory(struct kimage *image, const void *slave_code,
+		    const void *fdt, unsigned long kernel_load_addr,
+		    unsigned long fdt_load_addr, unsigned long stack_top,
+		    int debug)
+{
+	int ret, tree_node;
+	const void *prop;
+	unsigned long opal_base, opal_entry;
+	uint64_t toc;
+	unsigned int *slave_code_buf, master_entry;
+	unsigned int toc_section;
+
+	slave_code_buf = kmalloc(SLAVE_CODE_SIZE, GFP_KERNEL);
+	if (!slave_code_buf)
+		return -ENOMEM;
+
+	/* Get the slave code from the new kernel and put it in purgatory. */
+	ret = kexec_purgatory_get_set_symbol(image, "purgatory_start",
+					     slave_code_buf, SLAVE_CODE_SIZE,
+					     true);
+	if (ret) {
+		kfree(slave_code_buf);
+		return ret;
+	}
+
+	master_entry = slave_code_buf[0];
+	memcpy(slave_code_buf, slave_code, SLAVE_CODE_SIZE);
+	slave_code_buf[0] = master_entry;
+	ret = kexec_purgatory_get_set_symbol(image, "purgatory_start",
+					     slave_code_buf, SLAVE_CODE_SIZE,
+					     false);
+	kfree(slave_code_buf);
+
+	ret = kexec_purgatory_get_set_symbol(image, "kernel", &kernel_load_addr,
+					     sizeof(kernel_load_addr), false);
+	if (ret)
+		return ret;
+	ret = kexec_purgatory_get_set_symbol(image, "dt_offset", &fdt_load_addr,
+					     sizeof(fdt_load_addr), false);
+	if (ret)
+		return ret;
+
+	tree_node = fdt_path_offset(fdt, "/ibm,opal");
+	if (tree_node >= 0) {
+		prop = fdt_getprop(fdt, tree_node, "opal-base-address", NULL);
+		if (!prop) {
+			pr_err("OPAL address not found in the device tree.\n");
+			return -EINVAL;
+		}
+		opal_base = fdt64_to_cpu((const fdt64_t *) prop);
+
+		prop = fdt_getprop(fdt, tree_node, "opal-entry-address", NULL);
+		if (!prop) {
+			pr_err("OPAL address not found in the device tree.\n");
+			return -EINVAL;
+		}
+		opal_entry = fdt64_to_cpu((const fdt64_t *) prop);
+
+		ret = kexec_purgatory_get_set_symbol(image, "opal_base",
+						     &opal_base,
+						     sizeof(opal_base), false);
+		if (ret)
+			return ret;
+		ret = kexec_purgatory_get_set_symbol(image, "opal_entry",
+						     &opal_entry,
+						     sizeof(opal_entry), false);
+		if (ret)
+			return ret;
+	}
+
+	ret = kexec_purgatory_get_set_symbol(image, "stack", &stack_top,
+					     sizeof(stack_top), false);
+	if (ret)
+		return ret;
+
+	toc_section = elf_toc_section(image->purgatory_info.ehdr,
+				      image->purgatory_info.sechdrs);
+	if (!toc_section)
+		return -ENOEXEC;
+
+	toc = elf_my_r2(image->purgatory_info.sechdrs, toc_section);
+	ret = kexec_purgatory_get_set_symbol(image, "my_toc", &toc, sizeof(toc),
+					     false);
+	if (ret)
+		return ret;
+
+	pr_debug("Purgatory TOC is at 0x%llx\n", toc);
+
+	ret = kexec_purgatory_get_set_symbol(image, "debug", &debug,
+					     sizeof(debug), false);
+	if (ret)
+		return ret;
+	if (!debug)
+		pr_debug("Disabling purgatory output.\n");
+
+	return 0;
+}
+
+/**
+ * delete_fdt_mem_rsv - delete memory reservation with given address and size
+ *
+ * Return: 0 on success, or negative errno on error.
+ */
+static int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size)
+{
+	int i, ret, num_rsvs = fdt_num_mem_rsv(fdt);
+
+	for (i = 0; i < num_rsvs; i++) {
+		uint64_t rsv_start, rsv_size;
+
+		ret = fdt_get_mem_rsv(fdt, i, &rsv_start, &rsv_size);
+		if (ret) {
+			pr_err("Malformed device tree.\n");
+			return -EINVAL;
+		}
+
+		if (rsv_start == start && rsv_size == size) {
+			ret = fdt_del_mem_rsv(fdt, i);
+			if (ret) {
+				pr_err("Error deleting device tree reservation.\n");
+				return -EINVAL;
+			}
+
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+/*
+ * setup_new_fdt - modify /chosen and memory reservation for the next kernel
+ * @fdt:		Flattened device tree for the next kernel.
+ * @initrd_load_addr:	Address where the next initrd will be loaded.
+ * @initrd_len:		Size of the next initrd, or 0 if there will be none.
+ * @cmdline:		Command line for the next kernel, or NULL if there will
+ *			be none.
+ *
+ * Return: 0 on success, or negative errno on error.
+ */
+int setup_new_fdt(void *fdt, unsigned long initrd_load_addr,
+		  unsigned long initrd_len, const char *cmdline)
+{
+	int ret, chosen_node;
+	const void *prop;
+
+	/* Remove memory reservation for the current device tree. */
+	ret = delete_fdt_mem_rsv(fdt, __pa(initial_boot_params),
+				 fdt_totalsize(initial_boot_params));
+	if (ret == 0)
+		pr_debug("Removed old device tree reservation.\n");
+	else if (ret != -ENOENT)
+		return ret;
+
+	chosen_node = fdt_path_offset(fdt, "/chosen");
+	if (chosen_node == -FDT_ERR_NOTFOUND) {
+		chosen_node = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
+					      "chosen");
+		if (chosen_node < 0) {
+			pr_err("Error creating /chosen.\n");
+			return -EINVAL;
+		}
+	} else if (chosen_node < 0) {
+		pr_err("Malformed device tree: error reading /chosen.\n");
+		return -EINVAL;
+	}
+
+	/* Did we boot using an initrd? */
+	prop = fdt_getprop(fdt, chosen_node, "linux,initrd-start", NULL);
+	if (prop) {
+		uint64_t tmp_start, tmp_end, tmp_size;
+
+		tmp_start = fdt64_to_cpu(*((const fdt64_t *) prop));
+
+		prop = fdt_getprop(fdt, chosen_node, "linux,initrd-end", NULL);
+		if (!prop) {
+			pr_err("Malformed device tree.\n");
+			return -EINVAL;
+		}
+		tmp_end = fdt64_to_cpu(*((const fdt64_t *) prop));
+
+		/*
+		 * kexec reserves exact initrd size, while firmware may
+		 * reserve a multiple of PAGE_SIZE, so check for both.
+		 */
+		tmp_size = tmp_end - tmp_start;
+		ret = delete_fdt_mem_rsv(fdt, tmp_start, tmp_size);
+		if (ret == -ENOENT)
+			ret = delete_fdt_mem_rsv(fdt, tmp_start,
+						 round_up(tmp_size, PAGE_SIZE));
+		if (ret == 0)
+			pr_debug("Removed old initrd reservation.\n");
+		else if (ret != -ENOENT)
+			return ret;
+
+		/* If there's no new initrd, delete the old initrd's info. */
+		if (initrd_len == 0) {
+			ret = fdt_delprop(fdt, chosen_node,
+					  "linux,initrd-start");
+			if (ret) {
+				pr_err("Error deleting linux,initrd-start.\n");
+				return -EINVAL;
+			}
+
+			ret = fdt_delprop(fdt, chosen_node, "linux,initrd-end");
+			if (ret) {
+				pr_err("Error deleting linux,initrd-end.\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (initrd_len) {
+		ret = fdt_setprop_u64(fdt, chosen_node,
+				      "linux,initrd-start",
+				      initrd_load_addr);
+		if (ret < 0) {
+			pr_err("Error setting up the new device tree.\n");
+			return -EINVAL;
+		}
+
+		/* initrd-end is the first address after the initrd image. */
+		ret = fdt_setprop_u64(fdt, chosen_node, "linux,initrd-end",
+				      initrd_load_addr + initrd_len);
+		if (ret < 0) {
+			pr_err("Error setting up the new device tree.\n");
+			return -EINVAL;
+		}
+
+		ret = fdt_add_mem_rsv(fdt, initrd_load_addr, initrd_len);
+		if (ret) {
+			pr_err("Error reserving initrd memory: %s\n",
+			       fdt_strerror(ret));
+			return -EINVAL;
+		}
+	}
+
+	if (cmdline != NULL) {
+		ret = fdt_setprop_string(fdt, chosen_node, "bootargs", cmdline);
+		if (ret < 0) {
+			pr_err("Error setting up the new device tree.\n");
+			return -EINVAL;
+		}
+	} else {
+		ret = fdt_delprop(fdt, chosen_node, "bootargs");
+		if (ret && ret != -FDT_ERR_NOTFOUND) {
+			pr_err("Error deleting bootargs.\n");
+			return -EINVAL;
+		}
+	}
+
+	ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
+	if (ret) {
+		pr_err("Error setting up the new device tree.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * find_debug_console - find out whether there is a console for the purgatory
+ * @fdt:		Flattened device tree to search.
+ */
+bool find_debug_console(const void *fdt)
+{
+	int len;
+	int console_node, chosen_node;
+	const void *prop, *colon;
+
+	chosen_node = fdt_path_offset(fdt, "/chosen");
+	if (chosen_node < 0) {
+		pr_err("Malformed device tree: /chosen not found.\n");
+		return false;
+	}
+
+	prop = fdt_getprop(fdt, chosen_node, "stdout-path", &len);
+	if (prop == NULL) {
+		if (len == -FDT_ERR_NOTFOUND) {
+			prop = fdt_getprop(fdt, chosen_node,
+					   "linux,stdout-path", &len);
+			if (prop == NULL) {
+				pr_debug("Unable to find [linux,]stdout-path.\n");
+				return false;
+			}
+		} else {
+			pr_debug("Error finding console: %s\n",
+				 fdt_strerror(len));
+			return false;
+		}
+	}
+
+	/*
+	 * stdout-path can have a ':' separating the path from device-specific
+	 * information, so we should only consider what's before it.
+	 */
+	colon = strchr(prop, ':');
+	if (colon != NULL)
+		len = colon - prop;
+	else
+		len -= 1;	/* Ignore the terminating NUL. */
+
+	console_node = fdt_path_offset_namelen(fdt, prop, len);
+	if (console_node < 0) {
+		pr_debug("Error finding console: %s\n",
+			 fdt_strerror(console_node));
+		return false;
+	}
+
+	if (fdt_node_check_compatible(fdt, console_node, "hvterm1") == 0)
+		return true;
+	else if (fdt_node_check_compatible(fdt, console_node,
+					   "hvterm-protocol") == 0)
+		return true;
+
+	return false;
+}
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:40:16 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:40:16 -0200
Subject: [PATCH v9 09/10] powerpc: Add purgatory for kexec_file_load
 implementation.
In-Reply-To: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017617-8540-10-git-send-email-bauerman@linux.vnet.ibm.com>

This purgatory implementation comes from kexec-tools, almost unchanged.

In order to use boot/string.S in ppc64 big endian mode, the functions
defined in it need to have dot symbols so that they can be called from C
code. Therefore, change the file to use a DOTSYM macro if one is defined,
so that the purgatory can add those dot symbols.

The changes made to the purgatory code relative to the version in
kexec-tools were:

The sha256_regions global variable was renamed to sha_regions to match
what kexec_file_load expects, and to use the sha256.c file from x86's
purgatory (this avoids adding yet another SHA-256 implementation).

The global variables in purgatory.c and purgatory-ppc64.c now use a
__section attribute to put them in the .data section instead of being
initialized to zero. It doesn't matter what their initial value is,
because they will be set by the kernel when preparing the kexec image.

Also, since we don't support loading a crashdump kernel via
kexec_file_load yet, the code related to that functionality has been
removed.

Finally, some checkpatch.pl warnings were fixed.

Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
---
 arch/powerpc/Makefile                    |   1 +
 arch/powerpc/boot/string.S               |  67 +++++++------
 arch/powerpc/purgatory/.gitignore        |   2 +
 arch/powerpc/purgatory/Makefile          |  33 +++++++
 arch/powerpc/purgatory/console-ppc64.c   |  37 +++++++
 arch/powerpc/purgatory/crtsavres.S       |   5 +
 arch/powerpc/purgatory/hvCall.S          |  27 +++++
 arch/powerpc/purgatory/hvCall.h          |   8 ++
 arch/powerpc/purgatory/kexec-sha256.h    |  11 +++
 arch/powerpc/purgatory/ppc64_asm.h       |  20 ++++
 arch/powerpc/purgatory/printf.c          | 164 +++++++++++++++++++++++++++++++
 arch/powerpc/purgatory/purgatory-ppc64.c |  36 +++++++
 arch/powerpc/purgatory/purgatory.c       |  62 ++++++++++++
 arch/powerpc/purgatory/purgatory.h       |  14 +++
 arch/powerpc/purgatory/sha256.c          |   6 ++
 arch/powerpc/purgatory/sha256.h          |   1 +
 arch/powerpc/purgatory/string.S          |   2 +
 arch/powerpc/purgatory/v2wrap.S          | 134 +++++++++++++++++++++++++
 18 files changed, 601 insertions(+), 29 deletions(-)

diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 617dece67924..5e7dcdaf93f5 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -249,6 +249,7 @@ core-y				+= arch/powerpc/kernel/ \
 core-$(CONFIG_XMON)		+= arch/powerpc/xmon/
 core-$(CONFIG_KVM) 		+= arch/powerpc/kvm/
 core-$(CONFIG_PERF_EVENTS)	+= arch/powerpc/perf/
+core-$(CONFIG_KEXEC_FILE)	+= arch/powerpc/purgatory/
 
 drivers-$(CONFIG_OPROFILE)	+= arch/powerpc/oprofile/
 
diff --git a/arch/powerpc/boot/string.S b/arch/powerpc/boot/string.S
index acc9428f2789..b54bbad5f83d 100644
--- a/arch/powerpc/boot/string.S
+++ b/arch/powerpc/boot/string.S
@@ -11,9 +11,18 @@
 
 #include "ppc_asm.h"
 
+/*
+ * The ppc64 kexec purgatory uses this file and packages it in ELF64,
+ * so it needs dot symbols for the ppc64 big endian ABI. This macro
+ * allows it to create those symbols.
+ */
+#ifndef DOTSYM
+#define DOTSYM(a)	a
+#endif
+
 	.text
-	.globl	strcpy
-strcpy:
+	.globl	DOTSYM(strcpy)
+DOTSYM(strcpy):
 	addi	r5,r3,-1
 	addi	r4,r4,-1
 1:	lbzu	r0,1(r4)
@@ -22,8 +31,8 @@ strcpy:
 	bne	1b
 	blr
 
-	.globl	strncpy
-strncpy:
+	.globl	DOTSYM(strncpy)
+DOTSYM(strncpy):
 	cmpwi	0,r5,0
 	beqlr
 	mtctr	r5
@@ -35,8 +44,8 @@ strncpy:
 	bdnzf	2,1b		/* dec ctr, branch if ctr != 0 && !cr0.eq */
 	blr
 
-	.globl	strcat
-strcat:
+	.globl	DOTSYM(strcat)
+DOTSYM(strcat):
 	addi	r5,r3,-1
 	addi	r4,r4,-1
 1:	lbzu	r0,1(r5)
@@ -49,8 +58,8 @@ strcat:
 	bne	1b
 	blr
 
-	.globl	strchr
-strchr:
+	.globl	DOTSYM(strchr)
+DOTSYM(strchr):
 	addi	r3,r3,-1
 1:	lbzu	r0,1(r3)
 	cmpw	0,r0,r4
@@ -60,8 +69,8 @@ strchr:
 	li	r3,0
 	blr
 
-	.globl	strcmp
-strcmp:
+	.globl	DOTSYM(strcmp)
+DOTSYM(strcmp):
 	addi	r5,r3,-1
 	addi	r4,r4,-1
 1:	lbzu	r3,1(r5)
@@ -72,8 +81,8 @@ strcmp:
 	beq	1b
 	blr
 
-	.globl	strncmp
-strncmp:
+	.globl	DOTSYM(strncmp)
+DOTSYM(strncmp):
 	mtctr	r5
 	addi	r5,r3,-1
 	addi	r4,r4,-1
@@ -85,8 +94,8 @@ strncmp:
 	bdnzt	eq,1b
 	blr
 
-	.globl	strlen
-strlen:
+	.globl	DOTSYM(strlen)
+DOTSYM(strlen):
 	addi	r4,r3,-1
 1:	lbzu	r0,1(r4)
 	cmpwi	0,r0,0
@@ -94,8 +103,8 @@ strlen:
 	subf	r3,r3,r4
 	blr
 
-	.globl	memset
-memset:
+	.globl	DOTSYM(memset)
+DOTSYM(memset):
 	rlwimi	r4,r4,8,16,23
 	rlwimi	r4,r4,16,0,15
 	addi	r6,r3,-4
@@ -120,14 +129,14 @@ memset:
 	bdnz	8b
 	blr
 
-	.globl	memmove
-memmove:
+	.globl	DOTSYM(memmove)
+DOTSYM(memmove):
 	cmplw	0,r3,r4
-	bgt	backwards_memcpy
+	bgt	DOTSYM(backwards_memcpy)
 	/* fall through */
 
-	.globl	memcpy
-memcpy:
+	.globl	DOTSYM(memcpy)
+DOTSYM(memcpy):
 	rlwinm.	r7,r5,32-3,3,31		/* r7 = r5 >> 3 */
 	addi	r6,r3,-4
 	addi	r4,r4,-4
@@ -175,8 +184,8 @@ memcpy:
 	mtctr	r7
 	b	1b
 
-	.globl	backwards_memcpy
-backwards_memcpy:
+	.globl	DOTSYM(backwards_memcpy)
+DOTSYM(backwards_memcpy):
 	rlwinm.	r7,r5,32-3,3,31		/* r7 = r5 >> 3 */
 	add	r6,r3,r5
 	add	r4,r4,r5
@@ -219,8 +228,8 @@ backwards_memcpy:
 	mtctr	r7
 	b	1b
 
-	.globl	memchr
-memchr:
+	.globl	DOTSYM(memchr)
+DOTSYM(memchr):
 	cmpwi	0,r5,0
 	blelr
 	mtctr	r5
@@ -232,8 +241,8 @@ memchr:
 	li	r3,0
 	blr
 
-	.globl	memcmp
-memcmp:
+	.globl	DOTSYM(memcmp)
+DOTSYM(memcmp):
 	cmpwi	0,r5,0
 	ble	2f
 	mtctr	r5
@@ -253,8 +262,8 @@ memcmp:
  *
  * flush_cache(addr, len)
  */
-	.global	flush_cache
-flush_cache:
+	.globl	DOTSYM(flush_cache)
+DOTSYM(flush_cache):
 	addi	4,4,0x1f	/* len = (len + 0x1f) / 0x20 */
 	rlwinm.	4,4,27,5,31
 	mtctr	4
diff --git a/arch/powerpc/purgatory/.gitignore b/arch/powerpc/purgatory/.gitignore
new file mode 100644
index 000000000000..e9e66f178a6d
--- /dev/null
+++ b/arch/powerpc/purgatory/.gitignore
@@ -0,0 +1,2 @@
+kexec-purgatory.c
+purgatory.ro
diff --git a/arch/powerpc/purgatory/Makefile b/arch/powerpc/purgatory/Makefile
new file mode 100644
index 000000000000..32822234b049
--- /dev/null
+++ b/arch/powerpc/purgatory/Makefile
@@ -0,0 +1,33 @@
+OBJECT_FILES_NON_STANDARD := y
+
+purgatory-y := purgatory.o printf.o string.o v2wrap.o hvCall.o \
+		purgatory-ppc64.o console-ppc64.o  crtsavres.o sha256.o
+
+targets += $(purgatory-y)
+PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
+
+LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostartfiles \
+			-nostdlib -nodefaultlibs
+targets += purgatory.ro
+
+KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_FTRACE), $(KBUILD_CFLAGS))
+
+KBUILD_CFLAGS += -fno-zero-initialized-in-bss -fno-builtin -ffreestanding \
+		 -fno-stack-protector -fno-exceptions -fpie
+KBUILD_AFLAGS += -fno-exceptions -msoft-float -fpie
+
+$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
+		$(call if_changed,ld)
+
+targets += kexec-purgatory.c
+
+CMD_BIN2C = $(objtree)/scripts/basic/bin2c
+quiet_cmd_bin2c = BIN2C   $@
+      cmd_bin2c = $(CMD_BIN2C) kexec_purgatory < $< > $@
+
+$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
+	$(call if_changed,bin2c)
+	@:
+
+
+obj-$(CONFIG_KEXEC_FILE)	+= kexec-purgatory.o
diff --git a/arch/powerpc/purgatory/console-ppc64.c b/arch/powerpc/purgatory/console-ppc64.c
new file mode 100644
index 000000000000..8c89686fa340
--- /dev/null
+++ b/arch/powerpc/purgatory/console-ppc64.c
@@ -0,0 +1,37 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Created by: Mohan Kumar M (mohan at in.ibm.com)
+ *
+ * Copyright (C) IBM Corporation, 2005. All rights reserved
+ *
+ * Code taken from kexec-tools.
+ *
+ * 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.
+ */
+
+#include "hvCall.h"
+#include <asm/byteorder.h>
+#include "purgatory.h"
+
+void putchar(int c)
+{
+	char buff[8];
+	unsigned long *lbuf = (unsigned long *)buff;
+
+	if (!debug) /* running on non pseries */
+		return;
+
+	if (c == '\n')
+		putchar('\r');
+
+	buff[0] = c;
+	plpar_hcall_norets(H_PUT_TERM_CHAR, 0, 1, __cpu_to_be64(*lbuf), 0);
+}
diff --git a/arch/powerpc/purgatory/crtsavres.S b/arch/powerpc/purgatory/crtsavres.S
new file mode 100644
index 000000000000..5d17e1c0d575
--- /dev/null
+++ b/arch/powerpc/purgatory/crtsavres.S
@@ -0,0 +1,5 @@
+#ifndef CONFIG_CC_OPTIMIZE_FOR_SIZE
+#define CONFIG_CC_OPTIMIZE_FOR_SIZE 1
+#endif
+
+#include "../lib/crtsavres.S"
diff --git a/arch/powerpc/purgatory/hvCall.S b/arch/powerpc/purgatory/hvCall.S
new file mode 100644
index 000000000000..a96c4898f1d8
--- /dev/null
+++ b/arch/powerpc/purgatory/hvCall.S
@@ -0,0 +1,27 @@
+/*
+ * This file contains the generic function to perform a call to the
+ * pSeries LPAR hypervisor.
+ *
+ * Taken from linux/arch/powerpc/platforms/pseries/hvCall.S
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include "ppc64_asm.h"
+
+#define HVSC	.long 0x44000022
+.text
+	.machine ppc64
+.globl DOTSYM(plpar_hcall_norets)
+DOTSYM(plpar_hcall_norets):
+	or	6,6,6			# medium low priority
+        mfcr	0
+        stw	0,8(1)
+
+        HVSC 				/* invoke the hypervisor */
+
+        lwz	0,8(1)
+        mtcrf	0xff,0
+        blr                             /* return r3 = status */
diff --git a/arch/powerpc/purgatory/hvCall.h b/arch/powerpc/purgatory/hvCall.h
new file mode 100644
index 000000000000..187e24d8b964
--- /dev/null
+++ b/arch/powerpc/purgatory/hvCall.h
@@ -0,0 +1,8 @@
+#ifndef HVCALL_H
+#define HVCALL_H
+
+#define H_PUT_TERM_CHAR	0x58
+
+long plpar_hcall_norets(unsigned long opcode, ...);
+
+#endif
diff --git a/arch/powerpc/purgatory/kexec-sha256.h b/arch/powerpc/purgatory/kexec-sha256.h
new file mode 100644
index 000000000000..4418ed02c052
--- /dev/null
+++ b/arch/powerpc/purgatory/kexec-sha256.h
@@ -0,0 +1,11 @@
+#ifndef KEXEC_SHA256_H
+#define KEXEC_SHA256_H
+
+struct kexec_sha_region {
+	unsigned long start;
+	unsigned long len;
+};
+
+#define SHA256_REGIONS 16
+
+#endif /* KEXEC_SHA256_H */
diff --git a/arch/powerpc/purgatory/ppc64_asm.h b/arch/powerpc/purgatory/ppc64_asm.h
new file mode 100644
index 000000000000..95d721718237
--- /dev/null
+++ b/arch/powerpc/purgatory/ppc64_asm.h
@@ -0,0 +1,20 @@
+/*
+ * ppc64_asm.h - common defines for PPC64 assembly parts
+ *
+ * Code taken from kexec-tools.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <asm/types.h>
+
+/*
+ * ABIv1 requires dot symbol while ABIv2 does not.
+ */
+#ifdef PPC64_ELF_ABI_v2
+#define DOTSYM(a)	a
+#else
+#define GLUE(a, b)	a##b
+#define DOTSYM(a)	GLUE(., a)
+#endif
diff --git a/arch/powerpc/purgatory/printf.c b/arch/powerpc/purgatory/printf.c
new file mode 100644
index 000000000000..c5f425b55fd5
--- /dev/null
+++ b/arch/powerpc/purgatory/printf.c
@@ -0,0 +1,164 @@
+/*
+ * Code taken from kexec-tools.
+ *
+ * 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.
+ */
+
+#include <stdarg.h>
+#include "purgatory.h"
+#include "../boot/string.h"
+
+#define CHAR_BIT 8
+
+/*
+ * Output
+ * =============================================================================
+ */
+
+#define LONG_LONG_SHIFT  ((int)((sizeof(unsigned long long)*CHAR_BIT) - 4))
+#define LONG_SHIFT  ((int)((sizeof(unsigned long)*CHAR_BIT) - 4))
+#define INT_SHIFT   ((int)((sizeof(unsigned int)*CHAR_BIT) - 4))
+#define SHRT_SHIFT  ((int)((sizeof(unsigned short)*CHAR_BIT) - 4))
+#define CHAR_SHIFT  ((int)((sizeof(unsigned char)*CHAR_BIT) - 4))
+
+/**************************************************************************
+PRINTF and friends
+
+	Formats:
+		%x	- 4 bytes int (8 hex digits, lower case)
+		%X	- 4 bytes int (8 hex digits, upper case)
+		%lx     - 8 bytes long (16 hex digits, lower case)
+		%lX     - 8 bytes long (16 hex digits, upper case)
+		%hx	- 2 bytes int (4 hex digits, lower case)
+		%hX	- 2 bytes int (4 hex digits, upper case)
+		%hhx	- 1 byte int (2 hex digits, lower case)
+		%hhX	- 1 byte int (2 hex digits, upper case)
+			- optional # prefixes 0x or 0X
+		%d	- decimal int
+		%c	- char
+		%s	- string
+	Note: width specification not supported
+**************************************************************************/
+void vsprintf(char *buffer, const char *fmt, va_list args)
+{
+	char *p;
+
+	for ( ; *fmt != '\0'; ++fmt) {
+		if (*fmt != '%') {
+			if (buffer)
+				*buffer++ = *fmt;
+			else
+				putchar(*fmt);
+			continue;
+		}
+		if (*++fmt == 's') {
+			for (p = va_arg(args, char *); *p != '\0'; p++)
+				if (buffer)
+					*buffer++ = *p;
+				else
+					putchar(*p);
+		} else {	/* Length of item is bounded */
+			char tmp[40], *q = tmp;
+			int shift = INT_SHIFT;
+
+			if (*fmt == 'L') {
+				shift = LONG_LONG_SHIFT;
+				fmt++;
+			} else if (*fmt == 'l') {
+				shift = LONG_SHIFT;
+				fmt++;
+			} else if (*fmt == 'h') {
+				shift = SHRT_SHIFT;
+				fmt++;
+				if (*fmt == 'h') {
+					shift = CHAR_SHIFT;
+					fmt++;
+				}
+			}
+
+			/*
+			 * Before each format q points to tmp buffer
+			 * After each format q points past end of item
+			 */
+			if ((*fmt | 0x20) == 'x') {
+				/* With x86 gcc, sizeof(long) == sizeof(int) */
+				unsigned long long h;
+				int ncase;
+
+				if (shift > LONG_SHIFT)
+					h = va_arg(args, unsigned long long);
+				else if (shift > INT_SHIFT)
+					h = va_arg(args, unsigned long);
+				else
+					h = va_arg(args, unsigned int);
+
+				ncase = (*fmt & 0x20);
+				for ( ; shift >= 0; shift -= 4)
+					*q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
+			} else if (*fmt == 'd') {
+				char *r;
+				long i;
+
+				if (shift > LONG_SHIFT)
+					i = va_arg(args, long long);
+				else if (shift > INT_SHIFT)
+					i = va_arg(args, long);
+				else
+					i = va_arg(args, int);
+
+				if (i < 0) {
+					*q++ = '-';
+					i = -i;
+				}
+				p = q;		/* save beginning of digits */
+				do {
+					*q++ = '0' + (i % 10);
+					i /= 10;
+				} while (i);
+				/* reverse digits, stop in middle */
+				r = q;		/* don't alter q */
+				while (--r > p) {
+					i = *r;
+					*r = *p;
+					*p++ = i;
+				}
+			} else if (*fmt == 'c')
+				*q++ = va_arg(args, int);
+			else
+				*q++ = *fmt;
+			/* now output the saved string */
+			for (p = tmp; p < q; ++p)
+				if (buffer)
+					*buffer++ = *p;
+				else
+					putchar(*p);
+		}
+	}
+	if (buffer)
+		*buffer = '\0';
+}
+
+void sprintf(char *buffer, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vsprintf(buffer, fmt, args);
+	va_end(args);
+}
+
+void printf(const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vsprintf(0, fmt, args);
+	va_end(args);
+}
diff --git a/arch/powerpc/purgatory/purgatory-ppc64.c b/arch/powerpc/purgatory/purgatory-ppc64.c
new file mode 100644
index 000000000000..2e9545bcdcb4
--- /dev/null
+++ b/arch/powerpc/purgatory/purgatory-ppc64.c
@@ -0,0 +1,36 @@
+/*
+ * kexec: Linux boots Linux
+ *
+ * Created by: Mohan Kumar M (mohan at in.ibm.com)
+ *
+ * Copyright (C) IBM Corporation, 2005. All rights reserved
+ *
+ * Code taken from kexec-tools.
+ *
+ * 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.
+ */
+
+#include "purgatory.h"
+
+unsigned long stack __section(".data");
+unsigned long dt_offset __section(".data");
+unsigned long my_toc __section(".data");
+unsigned long kernel __section(".data");
+int debug __section(".data");
+unsigned long opal_base __section(".data");
+unsigned long opal_entry __section(".data");
+
+void setup_arch(void)
+{
+}
+
+void post_verification_setup_arch(void)
+{
+}
diff --git a/arch/powerpc/purgatory/purgatory.c b/arch/powerpc/purgatory/purgatory.c
new file mode 100644
index 000000000000..179f2da2b56f
--- /dev/null
+++ b/arch/powerpc/purgatory/purgatory.c
@@ -0,0 +1,62 @@
+/*
+ * Code taken from kexec-tools.
+ *
+ * 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.
+ */
+
+#include "purgatory.h"
+#include "sha256.h"
+#include "../boot/string.h"
+#include "kexec-sha256.h"
+
+struct kexec_sha_region sha_regions[SHA256_REGIONS] __section(".data");
+u8 sha256_digest[SHA256_DIGEST_SIZE] __section(".data");
+
+int verify_sha256_digest(void)
+{
+	struct kexec_sha_region *ptr, *end;
+	u8 digest[SHA256_DIGEST_SIZE];
+	size_t i;
+	struct sha256_state sctx;
+
+	sha256_init(&sctx);
+	end = &sha_regions[sizeof(sha_regions)/sizeof(sha_regions[0])];
+	for (ptr = sha_regions; ptr < end; ptr++)
+		sha256_update(&sctx, (uint8_t *)(ptr->start), ptr->len);
+	sha256_final(&sctx, digest);
+
+	if (memcmp(digest, sha256_digest, sizeof(digest)) != 0) {
+		printf("sha256 digests do not match :(\n");
+		printf("       digest: ");
+		for (i = 0; i < sizeof(digest); i++)
+			printf("%hhx ", digest[i]);
+		printf("\n");
+
+		printf("sha256_digest: ");
+		for (i = 0; i < sizeof(sha256_digest); i++)
+			printf("%hhx ", sha256_digest[i]);
+
+		printf("\n");
+		return 1;
+	}
+	return 0;
+}
+
+void purgatory(void)
+{
+	printf("I'm in purgatory\n");
+	setup_arch();
+	if (verify_sha256_digest()) {
+		/* loop forever */
+		for (;;)
+			;
+	}
+	post_verification_setup_arch();
+}
diff --git a/arch/powerpc/purgatory/purgatory.h b/arch/powerpc/purgatory/purgatory.h
new file mode 100644
index 000000000000..fde99e8b5043
--- /dev/null
+++ b/arch/powerpc/purgatory/purgatory.h
@@ -0,0 +1,14 @@
+#ifndef PURGATORY_H
+#define PURGATORY_H
+
+#include <linux/compiler.h>
+
+extern int debug;
+
+void putchar(int ch);
+void sprintf(char *buffer, const char *fmt, ...) __printf(2, 3);
+void printf(const char *fmt, ...) __printf(1, 2);
+void setup_arch(void);
+void post_verification_setup_arch(void);
+
+#endif /* PURGATORY_H */
diff --git a/arch/powerpc/purgatory/sha256.c b/arch/powerpc/purgatory/sha256.c
new file mode 100644
index 000000000000..6abee1877d56
--- /dev/null
+++ b/arch/powerpc/purgatory/sha256.c
@@ -0,0 +1,6 @@
+#include "../boot/string.h"
+
+/* Avoid including x86's boot/string.h in sha256.c. */
+#define BOOT_STRING_H
+
+#include "../../x86/purgatory/sha256.c"
diff --git a/arch/powerpc/purgatory/sha256.h b/arch/powerpc/purgatory/sha256.h
new file mode 100644
index 000000000000..72818f3a207e
--- /dev/null
+++ b/arch/powerpc/purgatory/sha256.h
@@ -0,0 +1 @@
+#include "../../x86/purgatory/sha256.h"
diff --git a/arch/powerpc/purgatory/string.S b/arch/powerpc/purgatory/string.S
new file mode 100644
index 000000000000..19d92e4e7554
--- /dev/null
+++ b/arch/powerpc/purgatory/string.S
@@ -0,0 +1,2 @@
+#include "ppc64_asm.h"
+#include "../boot/string.S"
diff --git a/arch/powerpc/purgatory/v2wrap.S b/arch/powerpc/purgatory/v2wrap.S
new file mode 100644
index 000000000000..c9a981c39a78
--- /dev/null
+++ b/arch/powerpc/purgatory/v2wrap.S
@@ -0,0 +1,134 @@
+#
+#  kexec: Linux boots Linux
+#
+#  Copyright (C) 2004 - 2005, Milton D Miller II, IBM Corporation
+#  Copyright (C) 2006, Mohan Kumar M (mohan at in.ibm.com), IBM Corporation
+#
+# Code taken from kexec-tools.
+#
+#  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.
+
+#include "ppc64_asm.h"
+
+# v2wrap.S
+# a wrapper to call purgatory code to backup first
+# 32kB of first kernel into the backup region
+# reserved by kexec-tools.
+# Invokes ppc64 kernel with the expected arguments
+# of kernel(device-tree, phys-offset, 0)
+
+#
+# calling convention:
+#   r3 = physical number of this cpu (all cpus)
+#   r4 = address of this chunk (master only)
+# master enters at purgatory_start (aka first byte of this chunk)
+# slaves (additional cpus), if any, enter a copy of the
+# first 0x100 bytes of this code relocated to 0x0
+#
+# in other words,
+#   a copy of the first 0x100 bytes of this code is copied to 0
+#   and the slaves are sent to address 0x60
+#   with r3 = their physical cpu number.
+
+#define LOADADDR(rn,name) \
+	lis     rn,name##@highest;      \
+	ori     rn,rn,name##@higher;    \
+	rldicr  rn,rn,32,31;            \
+	oris    rn,rn,name##@h;         \
+	ori     rn,rn,name##@l
+
+	.machine ppc64
+	.align 8
+	.globl purgatory_start
+purgatory_start:	b	master
+	.org purgatory_start + 0x5c     # ABI: possible run_at_load flag at 0x5c
+	.globl run_at_load
+run_at_load:
+	.long 0
+	.size run_at_load, . - run_at_load
+	.org purgatory_start + 0x60     # ABI: slaves start at 60 with r3=phys
+slave:	b $
+	.org purgatory_start + 0x100    # ABI: end of copied region
+	.size purgatory_start, . - purgatory_start
+
+#
+# The above 0x100 bytes at purgatory_start are replaced with the
+# code from the kernel (or next stage) by kexec/arch/ppc64/kexec-elf-ppc64.c
+#
+
+master:
+	or	1,1,1		# low priority to let other threads catchup
+	isync
+	mr      17,3            # save cpu id to r17
+	mr      15,4            # save physical address in reg15
+
+	LOADADDR(6,my_toc)
+	ld      2,0(6)          #setup toc
+
+	LOADADDR(6,stack)
+	ld      1,0(6)          #setup stack
+
+	subi    1,1,112
+	bl      DOTSYM(purgatory)
+	nop
+
+	or	3,3,3		# ok now to high priority, lets boot
+	lis	6,0x1
+	mtctr	6		# delay a bit for slaves to catch up
+83:	bdnz	83b		# before we overwrite 0-100 again
+
+	LOADADDR(16, dt_offset)
+	ld      3,0(16)         # load device-tree address
+	mr      16,3            # save dt address in reg16
+#ifdef __BIG_ENDIAN__
+	lwz     6,20(3)         # fetch version number
+#else
+	li	4,20
+	lwbrx	6,3,4		# fetch BE version number
+#endif
+	cmpwi   0,6,2           # v2 ?
+	blt     80f
+#ifdef __BIG_ENDIAN__
+	stw     17,28(3)        # save my cpu number as boot_cpu_phys
+#else
+	li	4,28
+	stwbrx	17,3,4		# Store my cpu as BE value
+#endif
+80:
+	LOADADDR(6,opal_base)	# For OPAL early debug
+	ld      8,0(6)          # load the OPAL base address in r8
+	LOADADDR(6,opal_entry)	# For OPAL early debug
+	ld      9,0(6)          # load the OPAL entry address in r9
+	LOADADDR(6,kernel)
+	ld      4,0(6)          # load the kernel address
+	LOADADDR(6,run_at_load) # the load flag
+	lwz	7,0(6)		# possibly patched by kexec-elf-ppc64
+	stw	7,0x5c(4)	# and patch it into the kernel
+	mr      3,16            # restore dt address
+
+	mfmsr	5
+	andi.	10,5,1		# test MSR_LE
+	bne	little_endian
+
+	li	5,0		# r5 will be 0 for kernel
+	mtctr	4		# prepare branch to
+	bctr			# start kernel
+
+little_endian:			# book3s-only
+	mtsrr0	4		# prepare branch to
+
+	clrrdi	5,5,1		# clear MSR_LE
+	mtsrr1	5
+
+	li	5,0		# r5 will be 0 for kernel
+
+				# skip cache flush, do we care?
+
+	rfid			# update MSR and start kernel
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:40:17 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:40:17 -0200
Subject: [PATCH v9 10/10] powerpc: Enable CONFIG_KEXEC_FILE in powerpc server
 defconfigs.
In-Reply-To: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017617-8540-11-git-send-email-bauerman@linux.vnet.ibm.com>

Enable CONFIG_KEXEC_FILE in powernv_defconfig, ppc64_defconfig and
pseries_defconfig.

It depends on CONFIG_CRYPTO_SHA256=y, so add that as well.

Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
---
 arch/powerpc/configs/powernv_defconfig | 2 ++
 arch/powerpc/configs/ppc64_defconfig   | 2 ++
 arch/powerpc/configs/pseries_defconfig | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig
index d98b6eb3254f..5a190aa5534b 100644
--- a/arch/powerpc/configs/powernv_defconfig
+++ b/arch/powerpc/configs/powernv_defconfig
@@ -49,6 +49,7 @@ CONFIG_BINFMT_MISC=m
 CONFIG_PPC_TRANSACTIONAL_MEM=y
 CONFIG_HOTPLUG_CPU=y
 CONFIG_KEXEC=y
+CONFIG_KEXEC_FILE=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_NUMA=y
 CONFIG_MEMORY_HOTPLUG=y
@@ -301,6 +302,7 @@ CONFIG_CRYPTO_CCM=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig
index 58a98d40086f..0059d2088b9c 100644
--- a/arch/powerpc/configs/ppc64_defconfig
+++ b/arch/powerpc/configs/ppc64_defconfig
@@ -46,6 +46,7 @@ CONFIG_HZ_100=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PPC_TRANSACTIONAL_MEM=y
 CONFIG_KEXEC=y
+CONFIG_KEXEC_FILE=y
 CONFIG_CRASH_DUMP=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTREMOVE=y
@@ -336,6 +337,7 @@ CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig
index 8a3bc016b732..f022f657a984 100644
--- a/arch/powerpc/configs/pseries_defconfig
+++ b/arch/powerpc/configs/pseries_defconfig
@@ -52,6 +52,7 @@ CONFIG_HZ_100=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PPC_TRANSACTIONAL_MEM=y
 CONFIG_KEXEC=y
+CONFIG_KEXEC_FILE=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
@@ -303,6 +304,7 @@ CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_ANUBIS=m
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:44:48 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:44:48 -0200
Subject: [PATCH v6 00/10] ima: carry the measurement list across kexec
Message-ID: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>

Hello,

This is just a rebase on top of kexec_file_load patches v9 which I just
posted. The previous version of this series has some conflicts with it.

Original cover letter:

The TPM PCRs are only reset on a hard reboot.  In order to validate a
TPM's quote after a soft reboot (eg. kexec -e), the IMA measurement list
of the running kernel must be saved and then restored on the subsequent
boot, possibly of a different architecture.

The existing securityfs binary_runtime_measurements file conveniently
provides a serialized format of the IMA measurement list. This patch
set serializes the measurement list in this format and restores it.

Up to now, the binary_runtime_measurements was defined as architecture
native format.  The assumption being that userspace could and would
handle any architecture conversions.  With the ability of carrying the
measurement list across kexec, possibly from one architecture to a
different one, the per boot architecture information is lost and with it
the ability of recalculating the template digest hash.  To resolve this
problem, without breaking the existing ABI, this patch set introduces
the boot command line option "ima_canonical_fmt", which is arbitrarily
defined as little endian.

The need for this boot command line option will be limited to the
existing version 1 format of the binary_runtime_measurements.
Subsequent formats will be defined as canonical format (eg. TPM 2.0
support for larger digests).

A simplified method of Thiago Bauermann's "kexec buffer handover" patch
series for carrying the IMA measurement list across kexec is included
in this patch set.  The simplified method requires all file measurements
be taken prior to executing the kexec load, as subsequent measurements
will not be carried across the kexec and restored.

Changelog v6:
- Rebased on top of "kexec_file_load implementation for PowerPC"
  patches v9.

Changelog v5:
- Included patches from Thiago Bauermann's "kexec buffer handover"
patch series for carrying the IMA measurement list across kexec.
- Added CONFIG_HAVE_IMA_KEXEC
- Renamed functions to variations of ima_kexec_buffer instead of
variations of kexec_handover_buffer

Changelog v4:
- Fixed "spinlock bad magic" BUG - reported by Dmitry Vyukov
- Rebased on Thiago Bauermann's v5 patch set
- Removed the skip_checksum initialization  

Changelog v3:
- Cleaned up the code for calculating the requested kexec segment size
needed for the IMA measurement list, limiting the segment size to half
of the totalram_pages.
- Fixed kernel test robot reports as enumerated in the respective
patch changelog.

Changelog v2:
- Canonical measurement list support added
- Redefined the ima_kexec_hdr struct to use well defined sizes

Andreas Steffen (1):
  ima: platform-independent hash value

Mimi Zohar (7):
  ima: on soft reboot, restore the measurement list
  ima: permit duplicate measurement list entries
  ima: maintain memory size needed for serializing the measurement list
  ima: on soft reboot, save the measurement list
  ima: store the builtin/custom template definitions in a list
  ima: support restoring multiple template formats
  ima: define a canonical binary_runtime_measurements list format

Thiago Jung Bauermann (2):
  powerpc: ima: Get the kexec buffer passed by the previous kernel
  powerpc: ima: Send the kexec buffer to the next kernel

 Documentation/kernel-parameters.txt         |   4 +
 arch/Kconfig                                |   3 +
 arch/powerpc/Kconfig                        |   1 +
 arch/powerpc/include/asm/ima.h              |  29 +++
 arch/powerpc/include/asm/kexec.h            |  15 +-
 arch/powerpc/kernel/Makefile                |   4 +
 arch/powerpc/kernel/ima_kexec.c             | 223 +++++++++++++++++++++
 arch/powerpc/kernel/kexec_elf_64.c          |   2 +-
 arch/powerpc/kernel/machine_kexec_file_64.c |  15 +-
 include/linux/ima.h                         |  12 ++
 kernel/kexec_file.c                         |   4 +
 security/integrity/ima/Kconfig              |  12 ++
 security/integrity/ima/Makefile             |   1 +
 security/integrity/ima/ima.h                |  31 +++
 security/integrity/ima/ima_crypto.c         |   6 +-
 security/integrity/ima/ima_fs.c             |  30 ++-
 security/integrity/ima/ima_init.c           |   2 +
 security/integrity/ima/ima_kexec.c          | 168 ++++++++++++++++
 security/integrity/ima/ima_main.c           |   1 +
 security/integrity/ima/ima_queue.c          |  76 +++++++-
 security/integrity/ima/ima_template.c       | 293 ++++++++++++++++++++++++++--
 security/integrity/ima/ima_template_lib.c   |   7 +-
 22 files changed, 901 insertions(+), 38 deletions(-)
 create mode 100644 arch/powerpc/include/asm/ima.h
 create mode 100644 arch/powerpc/kernel/ima_kexec.c
 create mode 100644 security/integrity/ima/ima_kexec.c

-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:44:49 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:44:49 -0200
Subject: [PATCH v6 01/10] powerpc: ima: Get the kexec buffer passed by the
 previous kernel
In-Reply-To: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017898-10375-2-git-send-email-bauerman@linux.vnet.ibm.com>

The IMA kexec buffer allows the currently running kernel to pass
the measurement list via a kexec segment to the kernel that will be
kexec'd. The second kernel can check whether the previous kernel sent
the buffer and retrieve it.

This is the architecture-specific part which enables IMA to receive the
measurement list passed by the previous kernel. It will be used in the
next patch.

The change in machine_kexec_64.c is to factor out the logic of removing
an FDT memory reservation so that it can be used by remove_ima_buffer.

Changelog v6:
- The kexec_file_load patches v9 already define delete_fdt_mem_rsv,
  so now we just need to export it.

Changelog v5:
- New patch in this version. This code was previously in the kexec buffer
  handover patch series.

Changelog relative to kexec handover patches v5:
- Added CONFIG_HAVE_IMA_KEXEC.
- Added arch/powerpc/include/asm/ima.h.
- Moved code to arch/powerpc/kernel/ima_kexec.c.
- Renamed functions to variations of ima_kexec_buffer instead of
  variations of kexec_handover_buffer.
- Use a single property /chosen/linux,ima-kexec-buffer containing
  the buffer address and length, instead of
  /chosen/linux,kexec-handover-buffer-{start,end}.
- Use #address-cells and #size-cells to read the DT property.
- Use size_t instead of unsigned long for size arguments.
- Always remove linux,ima-kexec-buffer and its memory reservation
  when preparing a device tree for kexec_file_load.

Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
Acked-by: "Eric W. Biederman" <ebiederm at xmission.com>
---
 arch/Kconfig                                |   3 +
 arch/powerpc/Kconfig                        |   1 +
 arch/powerpc/include/asm/ima.h              |  13 +++
 arch/powerpc/include/asm/kexec.h            |   1 +
 arch/powerpc/kernel/Makefile                |   4 +
 arch/powerpc/kernel/ima_kexec.c             | 132 ++++++++++++++++++++++++++++
 arch/powerpc/kernel/machine_kexec_file_64.c |   5 +-
 7 files changed, 158 insertions(+), 1 deletion(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 659bdd079277..e1605ff286a1 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -5,6 +5,9 @@
 config KEXEC_CORE
 	bool
 
+config HAVE_IMA_KEXEC
+	bool
+
 config OPROFILE
 	tristate "OProfile system profiling"
 	depends on PROFILING
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 897d0f14447d..40ee044f1915 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -458,6 +458,7 @@ config KEXEC
 config KEXEC_FILE
 	bool "kexec file based system call"
 	select KEXEC_CORE
+	select HAVE_IMA_KEXEC
 	select BUILD_BIN2C
 	depends on PPC64
 	depends on CRYPTO=y
diff --git a/arch/powerpc/include/asm/ima.h b/arch/powerpc/include/asm/ima.h
new file mode 100644
index 000000000000..d5a72dd9b499
--- /dev/null
+++ b/arch/powerpc/include/asm/ima.h
@@ -0,0 +1,13 @@
+#ifndef _ASM_POWERPC_IMA_H
+#define _ASM_POWERPC_IMA_H
+
+int ima_get_kexec_buffer(void **addr, size_t *size);
+int ima_free_kexec_buffer(void);
+
+#ifdef CONFIG_IMA
+void remove_ima_buffer(void *fdt, int chosen_node);
+#else
+static inline void remove_ima_buffer(void *fdt, int chosen_node) {}
+#endif
+
+#endif /* _ASM_POWERPC_IMA_H */
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index 4497db7555b0..23056d2dc330 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -101,6 +101,7 @@ int setup_purgatory(struct kimage *image, const void *slave_code,
 int setup_new_fdt(void *fdt, unsigned long initrd_load_addr,
 		  unsigned long initrd_len, const char *cmdline);
 bool find_debug_console(const void *fdt);
+int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size);
 #endif /* CONFIG_KEXEC_FILE */
 
 #else /* !CONFIG_KEXEC_CORE */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 424b13b1b2b0..c3b37171168c 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -111,6 +111,10 @@ obj-$(CONFIG_KEXEC_CORE)	+= machine_kexec.o crash.o \
 				   machine_kexec_$(BITS).o
 obj-$(CONFIG_KEXEC_FILE)	+= machine_kexec_file_$(BITS).o elf_util.o \
 				   kexec_elf_$(BITS).o
+ifeq ($(CONFIG_HAVE_IMA_KEXEC)$(CONFIG_IMA),yy)
+obj-y				+= ima_kexec.o
+endif
+
 obj-$(CONFIG_AUDIT)		+= audit.o
 obj64-$(CONFIG_AUDIT)		+= compat_audit.o
 
diff --git a/arch/powerpc/kernel/ima_kexec.c b/arch/powerpc/kernel/ima_kexec.c
new file mode 100644
index 000000000000..36e5a5df3804
--- /dev/null
+++ b/arch/powerpc/kernel/ima_kexec.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2016 IBM Corporation
+ *
+ * Authors:
+ * Thiago Jung Bauermann <bauerman at linux.vnet.ibm.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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/slab.h>
+#include <linux/kexec.h>
+#include <linux/of.h>
+#include <linux/memblock.h>
+#include <linux/libfdt.h>
+
+static int get_addr_size_cells(int *addr_cells, int *size_cells)
+{
+	struct device_node *root;
+
+	root = of_find_node_by_path("/");
+	if (!root)
+		return -EINVAL;
+
+	*addr_cells = of_n_addr_cells(root);
+	*size_cells = of_n_size_cells(root);
+
+	of_node_put(root);
+
+	return 0;
+}
+
+static int do_get_kexec_buffer(const void *prop, int len, unsigned long *addr,
+			       size_t *size)
+{
+	int ret, addr_cells, size_cells;
+
+	ret = get_addr_size_cells(&addr_cells, &size_cells);
+	if (ret)
+		return ret;
+
+	if (len < 4 * (addr_cells + size_cells))
+		return -ENOENT;
+
+	*addr = of_read_number(prop, addr_cells);
+	*size = of_read_number(prop + 4 * addr_cells, size_cells);
+
+	return 0;
+}
+
+/**
+ * ima_get_kexec_buffer - get IMA buffer from the previous kernel
+ * @addr:	On successful return, set to point to the buffer contents.
+ * @size:	On successful return, set to the buffer size.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int ima_get_kexec_buffer(void **addr, size_t *size)
+{
+	int ret, len;
+	unsigned long tmp_addr;
+	size_t tmp_size;
+	const void *prop;
+
+	prop = of_get_property(of_chosen, "linux,ima-kexec-buffer", &len);
+	if (!prop)
+		return -ENOENT;
+
+	ret = do_get_kexec_buffer(prop, len, &tmp_addr, &tmp_size);
+	if (ret)
+		return ret;
+
+	*addr = __va(tmp_addr);
+	*size = tmp_size;
+
+	return 0;
+}
+
+/**
+ * ima_free_kexec_buffer - free memory used by the IMA buffer
+ */
+int ima_free_kexec_buffer(void)
+{
+	int ret;
+	unsigned long addr;
+	size_t size;
+	struct property *prop;
+
+	prop = of_find_property(of_chosen, "linux,ima-kexec-buffer", NULL);
+	if (!prop)
+		return -ENOENT;
+
+	ret = do_get_kexec_buffer(prop->value, prop->length, &addr, &size);
+	if (ret)
+		return ret;
+
+	ret = of_remove_property(of_chosen, prop);
+	if (ret)
+		return ret;
+
+	return memblock_free(addr, size);
+
+}
+
+/**
+ * remove_ima_buffer - remove the IMA buffer property and reservation from @fdt
+ *
+ * The IMA measurement buffer is of no use to a subsequent kernel, so we always
+ * remove it from the device tree.
+ */
+void remove_ima_buffer(void *fdt, int chosen_node)
+{
+	int ret, len;
+	unsigned long addr;
+	size_t size;
+	const void *prop;
+
+	prop = fdt_getprop(fdt, chosen_node, "linux,ima-kexec-buffer", &len);
+	if (!prop)
+		return;
+
+	ret = do_get_kexec_buffer(prop, len, &addr, &size);
+	fdt_delprop(fdt, chosen_node, "linux,ima-kexec-buffer");
+	if (ret)
+		return;
+
+	ret = delete_fdt_mem_rsv(fdt, addr, size);
+	if (!ret)
+		pr_debug("Removed old IMA buffer reservation.\n");
+}
diff --git a/arch/powerpc/kernel/machine_kexec_file_64.c b/arch/powerpc/kernel/machine_kexec_file_64.c
index 9acc56d199f0..7b13634f71bf 100644
--- a/arch/powerpc/kernel/machine_kexec_file_64.c
+++ b/arch/powerpc/kernel/machine_kexec_file_64.c
@@ -28,6 +28,7 @@
 #include <linux/of_fdt.h>
 #include <linux/libfdt.h>
 #include <asm/elf_util.h>
+#include <asm/ima.h>
 
 #define SLAVE_CODE_SIZE		256
 
@@ -363,7 +364,7 @@ int setup_purgatory(struct kimage *image, const void *slave_code,
  *
  * Return: 0 on success, or negative errno on error.
  */
-static int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size)
+int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size)
 {
 	int i, ret, num_rsvs = fdt_num_mem_rsv(fdt);
 
@@ -511,6 +512,8 @@ int setup_new_fdt(void *fdt, unsigned long initrd_load_addr,
 		}
 	}
 
+	remove_ima_buffer(fdt, chosen_node);
+
 	ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
 	if (ret) {
 		pr_err("Error setting up the new device tree.\n");
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:44:50 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:44:50 -0200
Subject: [PATCH v6 02/10] ima: on soft reboot, restore the measurement list
In-Reply-To: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017898-10375-3-git-send-email-bauerman@linux.vnet.ibm.com>

From: Mimi Zohar <zohar at linux.vnet.ibm.com>

The TPM PCRs are only reset on a hard reboot.  In order to validate a
TPM's quote after a soft reboot (eg. kexec -e), the IMA measurement list
of the running kernel must be saved and restored on boot.  This patch
restores the measurement list.

Changelog v5:
- replace CONFIG_KEXEC_FILE with architecture CONFIG_HAVE_IMA_KEXEC (Thiago)
- replace kexec_get_handover_buffer() with ima_get_kexec_buffer() (Thiago)
- replace kexec_free_handover_buffer() with ima_free_kexec_buffer() (Thiago)
- remove unnecessary includes from ima_kexec.c (Thiago)
- fix off-by-one error when checking hdr_v1->template_name_len (Colin King)

Changelog v2:
- redefined ima_kexec_hdr to use types with well defined sizes (M. Ellerman)
- defined missing ima_load_kexec_buffer() stub function

Changelog v1:
- call ima_load_kexec_buffer() (Thiago)

Signed-off-by: Mimi Zohar <zohar at linux.vnet.ibm.com>
---
 security/integrity/ima/Makefile       |   1 +
 security/integrity/ima/ima.h          |  21 +++++
 security/integrity/ima/ima_init.c     |   2 +
 security/integrity/ima/ima_kexec.c    |  44 +++++++++
 security/integrity/ima/ima_queue.c    |  10 ++
 security/integrity/ima/ima_template.c | 170 ++++++++++++++++++++++++++++++++++
 6 files changed, 248 insertions(+)

diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
index 9aeaedad1e2b..29f198bde02b 100644
--- a/security/integrity/ima/Makefile
+++ b/security/integrity/ima/Makefile
@@ -8,4 +8,5 @@ obj-$(CONFIG_IMA) += ima.o
 ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
 	 ima_policy.o ima_template.o ima_template_lib.o
 ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
+ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
 obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index db25f54a04fe..51dc8d57d64d 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -28,6 +28,10 @@
 
 #include "../integrity.h"
 
+#ifdef CONFIG_HAVE_IMA_KEXEC
+#include <asm/ima.h>
+#endif
+
 enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN,
 		     IMA_SHOW_BINARY_OLD_STRING_FMT, IMA_SHOW_ASCII };
 enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
@@ -102,6 +106,21 @@ struct ima_queue_entry {
 };
 extern struct list_head ima_measurements;	/* list of all measurements */
 
+/* Some details preceding the binary serialized measurement list */
+struct ima_kexec_hdr {
+	u16 version;
+	u16 _reserved0;
+	u32 _reserved1;
+	u64 buffer_size;
+	u64 count;
+};
+
+#ifdef CONFIG_HAVE_IMA_KEXEC
+void ima_load_kexec_buffer(void);
+#else
+static inline void ima_load_kexec_buffer(void) {}
+#endif /* CONFIG_HAVE_IMA_KEXEC */
+
 /* Internal IMA function definitions */
 int ima_init(void);
 int ima_fs_init(void);
@@ -122,6 +141,8 @@ int ima_init_crypto(void);
 void ima_putc(struct seq_file *m, void *data, int datalen);
 void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
 struct ima_template_desc *ima_template_desc_current(void);
+int ima_restore_measurement_entry(struct ima_template_entry *entry);
+int ima_restore_measurement_list(loff_t bufsize, void *buf);
 int ima_init_template(void);
 
 /*
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 32912bd54ead..3ba0ca49cba6 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -128,6 +128,8 @@ int __init ima_init(void)
 	if (rc != 0)
 		return rc;
 
+	ima_load_kexec_buffer();
+
 	rc = ima_add_boot_aggregate();	/* boot aggregate must be first entry */
 	if (rc != 0)
 		return rc;
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
new file mode 100644
index 000000000000..36afd0fe9747
--- /dev/null
+++ b/security/integrity/ima/ima_kexec.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 IBM Corporation
+ *
+ * Authors:
+ * Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
+ * Mimi Zohar <zohar at linux.vnet.ibm.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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include "ima.h"
+
+/*
+ * Restore the measurement list from the previous kernel.
+ */
+void ima_load_kexec_buffer(void)
+{
+	void *kexec_buffer = NULL;
+	size_t kexec_buffer_size = 0;
+	int rc;
+
+	rc = ima_get_kexec_buffer(&kexec_buffer, &kexec_buffer_size);
+	switch (rc) {
+	case 0:
+		rc = ima_restore_measurement_list(kexec_buffer_size,
+						  kexec_buffer);
+		if (rc != 0)
+			pr_err("Failed to restore the measurement list: %d\n",
+				rc);
+
+		ima_free_kexec_buffer();
+		break;
+	case -ENOTSUPP:
+		pr_debug("Restoring the measurement list not supported\n");
+		break;
+	case -ENOENT:
+		pr_debug("No measurement list to restore\n");
+		break;
+	default:
+		pr_debug("Error restoring the measurement list: %d\n", rc);
+	}
+}
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 32f6ac0f96df..4b1bb7787839 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -149,3 +149,13 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
 			    op, audit_cause, result, audit_info);
 	return result;
 }
+
+int ima_restore_measurement_entry(struct ima_template_entry *entry)
+{
+	int result = 0;
+
+	mutex_lock(&ima_extend_list_mutex);
+	result = ima_add_digest_entry(entry);
+	mutex_unlock(&ima_extend_list_mutex);
+	return result;
+}
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index febd12ed9b55..37f972cb05fe 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -37,6 +37,7 @@ static struct ima_template_field supported_fields[] = {
 	{.field_id = "sig", .field_init = ima_eventsig_init,
 	 .field_show = ima_show_template_sig},
 };
+#define MAX_TEMPLATE_NAME_LEN 15
 
 static struct ima_template_desc *ima_template;
 static struct ima_template_desc *lookup_template_desc(const char *name);
@@ -205,3 +206,172 @@ int __init ima_init_template(void)
 
 	return result;
 }
+
+static int ima_restore_template_data(struct ima_template_desc *template_desc,
+				     void *template_data,
+				     int template_data_size,
+				     struct ima_template_entry **entry)
+{
+	struct binary_field_data {
+		u32 len;
+		u8 data[0];
+	} __packed;
+
+	struct binary_field_data *field_data;
+	int offset = 0;
+	int ret = 0;
+	int i;
+
+	*entry = kzalloc(sizeof(**entry) +
+		    template_desc->num_fields * sizeof(struct ima_field_data),
+		    GFP_NOFS);
+	if (!*entry)
+		return -ENOMEM;
+
+	(*entry)->template_desc = template_desc;
+	for (i = 0; i < template_desc->num_fields; i++) {
+		field_data = template_data + offset;
+
+		/* Each field of the template data is prefixed with a length. */
+		if (offset > (template_data_size - sizeof(field_data->len))) {
+			pr_err("Restoring the template field failed\n");
+			ret = -EINVAL;
+			break;
+		}
+		offset += sizeof(field_data->len);
+
+		if (offset > (template_data_size - field_data->len)) {
+			pr_err("Restoring the template field data failed\n");
+			ret = -EINVAL;
+			break;
+		}
+		offset += field_data->len;
+
+		(*entry)->template_data[i].len = field_data->len;
+		(*entry)->template_data_len += sizeof(field_data->len);
+
+		(*entry)->template_data[i].data =
+			kzalloc(field_data->len + 1, GFP_KERNEL);
+		if (!(*entry)->template_data[i].data) {
+			ret = -ENOMEM;
+			break;
+		}
+		memcpy((*entry)->template_data[i].data, field_data->data,
+			field_data->len);
+		(*entry)->template_data_len += field_data->len;
+	}
+
+	if (ret < 0) {
+		ima_free_template_entry(*entry);
+		*entry = NULL;
+	}
+
+	return ret;
+}
+
+/* Restore the serialized binary measurement list without extending PCRs. */
+int ima_restore_measurement_list(loff_t size, void *buf)
+{
+	struct binary_hdr_v1 {
+		u32 pcr;
+		u8 digest[TPM_DIGEST_SIZE];
+		u32 template_name_len;
+		char template_name[0];
+	} __packed;
+	char template_name[MAX_TEMPLATE_NAME_LEN];
+
+	struct binary_data_v1 {
+		u32 template_data_size;
+		char template_data[0];
+	} __packed;
+
+	struct ima_kexec_hdr *khdr = buf;
+	struct binary_hdr_v1 *hdr_v1;
+	struct binary_data_v1 *data_v1;
+
+	void *bufp = buf + sizeof(*khdr);
+	void *bufendp = buf + khdr->buffer_size;
+	struct ima_template_entry *entry;
+	struct ima_template_desc *template_desc;
+	unsigned long count = 0;
+	int ret = 0;
+
+	if (!buf || size < sizeof(*khdr))
+		return 0;
+
+	if (khdr->version != 1) {
+		pr_err("attempting to restore a incompatible measurement list");
+		return 0;
+	}
+
+	/*
+	 * ima kexec buffer prefix: version, buffer size, count
+	 * v1 format: pcr, digest, template-name-len, template-name,
+	 *	      template-data-size, template-data
+	 */
+	while ((bufp < bufendp) && (count++ < khdr->count)) {
+		if (count > ULONG_MAX - 1) {
+			pr_err("attempting to restore too many measurements");
+			ret = -EINVAL;
+		}
+
+		hdr_v1 = bufp;
+		if ((hdr_v1->template_name_len >= MAX_TEMPLATE_NAME_LEN) ||
+		    ((bufp + hdr_v1->template_name_len) > bufendp)) {
+			pr_err("attempting to restore a template name \
+				that is too long\n");
+			ret = -EINVAL;
+			break;
+		}
+		bufp += sizeof(*hdr_v1);
+
+		/* template name is not null terminated */
+		memcpy(template_name, bufp, hdr_v1->template_name_len);
+		template_name[hdr_v1->template_name_len] = 0;
+
+		if (strcmp(template_name, "ima") == 0) {
+			pr_err("attempting to restore an unsupported \
+				template \"%s\" failed\n", template_name);
+			ret = -EINVAL;
+			break;
+		}
+		data_v1 = bufp += (u_int8_t)hdr_v1->template_name_len;
+
+		/* get template format */
+		template_desc = lookup_template_desc(template_name);
+		if (!template_desc) {
+			pr_err("template \"%s\" not found\n", template_name);
+			ret = -EINVAL;
+			break;
+		}
+
+		if (bufp > (bufendp - sizeof(data_v1->template_data_size))) {
+			pr_err("restoring the template data size failed\n");
+			ret = -EINVAL;
+			break;
+		}
+		bufp += (u_int8_t) sizeof(data_v1->template_data_size);
+
+		if (bufp > (bufendp - data_v1->template_data_size)) {
+			pr_err("restoring the template data failed\n");
+			ret = -EINVAL;
+			break;
+		}
+
+		ret = ima_restore_template_data(template_desc,
+						data_v1->template_data,
+						data_v1->template_data_size,
+						&entry);
+		if (ret < 0)
+			break;
+
+		memcpy(entry->digest, hdr_v1->digest, TPM_DIGEST_SIZE);
+		entry->pcr = hdr_v1->pcr;
+		ret = ima_restore_measurement_entry(entry);
+		if (ret < 0)
+			break;
+
+		bufp += data_v1->template_data_size;
+	}
+	return ret;
+}
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:44:51 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:44:51 -0200
Subject: [PATCH v6 03/10] ima: permit duplicate measurement list entries
In-Reply-To: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017898-10375-4-git-send-email-bauerman@linux.vnet.ibm.com>

From: Mimi Zohar <zohar at linux.vnet.ibm.com>

Measurements carried across kexec need to be added to the IMA
measurement list, but should not prevent measurements of the newly
booted kernel from being added to the measurement list. This patch
adds support for allowing duplicate measurements.

The "boot_aggregate" measurement entry is the delimiter between soft
boots.

Signed-off-by: Mimi Zohar <zohar at linux.vnet.ibm.com>
---
 security/integrity/ima/ima_queue.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 4b1bb7787839..12d1b040bca9 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -65,11 +65,12 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
 }
 
 /* ima_add_template_entry helper function:
- * - Add template entry to measurement list and hash table.
+ * - Add template entry to the measurement list and hash table, for
+ *   all entries except those carried across kexec.
  *
  * (Called with ima_extend_list_mutex held.)
  */
-static int ima_add_digest_entry(struct ima_template_entry *entry)
+static int ima_add_digest_entry(struct ima_template_entry *entry, int flags)
 {
 	struct ima_queue_entry *qe;
 	unsigned int key;
@@ -85,8 +86,10 @@ static int ima_add_digest_entry(struct ima_template_entry *entry)
 	list_add_tail_rcu(&qe->later, &ima_measurements);
 
 	atomic_long_inc(&ima_htable.len);
-	key = ima_hash_key(entry->digest);
-	hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
+	if (flags) {
+		key = ima_hash_key(entry->digest);
+		hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
+	}
 	return 0;
 }
 
@@ -126,7 +129,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
 		}
 	}
 
-	result = ima_add_digest_entry(entry);
+	result = ima_add_digest_entry(entry, 1);
 	if (result < 0) {
 		audit_cause = "ENOMEM";
 		audit_info = 0;
@@ -155,7 +158,7 @@ int ima_restore_measurement_entry(struct ima_template_entry *entry)
 	int result = 0;
 
 	mutex_lock(&ima_extend_list_mutex);
-	result = ima_add_digest_entry(entry);
+	result = ima_add_digest_entry(entry, 0);
 	mutex_unlock(&ima_extend_list_mutex);
 	return result;
 }
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:44:52 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:44:52 -0200
Subject: [PATCH v6 04/10] ima: maintain memory size needed for serializing the
 measurement list
In-Reply-To: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017898-10375-5-git-send-email-bauerman@linux.vnet.ibm.com>

From: Mimi Zohar <zohar at linux.vnet.ibm.com>

In preparation for serializing the binary_runtime_measurements, this patch
maintains the amount of memory required.

Changelog v5:
- replace CONFIG_KEXEC_FILE with architecture CONFIG_HAVE_IMA_KEXEC (Thiago)

Changelog v3:
- include the ima_kexec_hdr size in the binary_runtime_measurement size.

Signed-off-by: Mimi Zohar <zohar at linux.vnet.ibm.com>
---
 security/integrity/ima/Kconfig     | 12 +++++++++
 security/integrity/ima/ima.h       |  1 +
 security/integrity/ima/ima_queue.c | 53 ++++++++++++++++++++++++++++++++++++--
 3 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 5487827fa86c..370eb2f4dd37 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -27,6 +27,18 @@ config IMA
 	  to learn more about IMA.
 	  If unsure, say N.
 
+config IMA_KEXEC
+	bool "Enable carrying the IMA measurement list across a soft boot"
+	depends on IMA && TCG_TPM && HAVE_IMA_KEXEC
+	default n
+	help
+	   TPM PCRs are only reset on a hard reboot.  In order to validate
+	   a TPM's quote after a soft boot, the IMA measurement list of the
+	   running kernel must be saved and restored on boot.
+
+	   Depending on the IMA policy, the measurement list can grow to
+	   be very large.
+
 config IMA_MEASURE_PCR_IDX
 	int
 	depends on IMA
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 51dc8d57d64d..ea1dcc452911 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -143,6 +143,7 @@ void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
 struct ima_template_desc *ima_template_desc_current(void);
 int ima_restore_measurement_entry(struct ima_template_entry *entry);
 int ima_restore_measurement_list(loff_t bufsize, void *buf);
+unsigned long ima_get_binary_runtime_size(void);
 int ima_init_template(void);
 
 /*
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 12d1b040bca9..3a3cc2a45645 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -29,6 +29,11 @@
 #define AUDIT_CAUSE_LEN_MAX 32
 
 LIST_HEAD(ima_measurements);	/* list of all measurements */
+#ifdef CONFIG_IMA_KEXEC
+static unsigned long binary_runtime_size;
+#else
+static unsigned long binary_runtime_size = ULONG_MAX;
+#endif
 
 /* key: inode (before secure-hashing a file) */
 struct ima_h_table ima_htable = {
@@ -64,6 +69,24 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
 	return ret;
 }
 
+/*
+ * Calculate the memory required for serializing a single
+ * binary_runtime_measurement list entry, which contains a
+ * couple of variable length fields (e.g template name and data).
+ */
+static int get_binary_runtime_size(struct ima_template_entry *entry)
+{
+	int size = 0;
+
+	size += sizeof(u32);	/* pcr */
+	size += sizeof(entry->digest);
+	size += sizeof(int);	/* template name size field */
+	size += strlen(entry->template_desc->name);
+	size += sizeof(entry->template_data_len);
+	size += entry->template_data_len;
+	return size;
+}
+
 /* ima_add_template_entry helper function:
  * - Add template entry to the measurement list and hash table, for
  *   all entries except those carried across kexec.
@@ -90,9 +113,30 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, int flags)
 		key = ima_hash_key(entry->digest);
 		hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
 	}
+
+	if (binary_runtime_size != ULONG_MAX) {
+		int size;
+
+		size = get_binary_runtime_size(entry);
+		binary_runtime_size = (binary_runtime_size < ULONG_MAX - size) ?
+		     binary_runtime_size + size : ULONG_MAX;
+	}
 	return 0;
 }
 
+/*
+ * Return the amount of memory required for serializing the
+ * entire binary_runtime_measurement list, including the ima_kexec_hdr
+ * structure.
+ */
+unsigned long ima_get_binary_runtime_size(void)
+{
+	if (binary_runtime_size >= (ULONG_MAX - sizeof(struct ima_kexec_hdr)))
+		return ULONG_MAX;
+	else
+		return binary_runtime_size + sizeof(struct ima_kexec_hdr);
+};
+
 static int ima_pcr_extend(const u8 *hash, int pcr)
 {
 	int result = 0;
@@ -106,8 +150,13 @@ static int ima_pcr_extend(const u8 *hash, int pcr)
 	return result;
 }
 
-/* Add template entry to the measurement list and hash table,
- * and extend the pcr.
+/*
+ * Add template entry to the measurement list and hash table, and
+ * extend the pcr.
+ *
+ * On systems which support carrying the IMA measurement list across
+ * kexec, maintain the total memory size required for serializing the
+ * binary_runtime_measurements.
  */
 int ima_add_template_entry(struct ima_template_entry *entry, int violation,
 			   const char *op, struct inode *inode,
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:44:53 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:44:53 -0200
Subject: [PATCH v6 05/10] powerpc: ima: Send the kexec buffer to the next
 kernel
In-Reply-To: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017898-10375-6-git-send-email-bauerman@linux.vnet.ibm.com>

The IMA kexec buffer allows the currently running kernel to pass
the measurement list via a kexec segment to the kernel that will be
kexec'd.

This is the architecture-specific part of setting up the IMA kexec
buffer for the next kernel. It will be used in the next patch.

Changelog v5:
- New patch in this version. This code was previously in the kexec buffer
  handover patch series.

Changelog relative to kexec handover patches v5:
- Moved code to arch/powerpc/kernel/ima_kexec.c.
- Renamed functions and struct members to variations of ima_kexec_buffer
  instead of variations of kexec_handover_buffer.
- Use a single property /chosen/linux,ima-kexec-buffer containing
  the buffer address and length, instead of
  /chosen/linux,kexec-handover-buffer-{start,end}.
- Use #address-cells and #size-cells to write the DT property.
- Use size_t instead of unsigned long for size arguments.
- Use CONFIG_IMA_KEXEC to build this code only when necessary.

Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
Acked-by: "Eric W. Biederman" <ebiederm at xmission.com>
---
 arch/powerpc/include/asm/ima.h              | 16 +++++
 arch/powerpc/include/asm/kexec.h            | 14 ++++-
 arch/powerpc/kernel/ima_kexec.c             | 91 +++++++++++++++++++++++++++++
 arch/powerpc/kernel/kexec_elf_64.c          |  2 +-
 arch/powerpc/kernel/machine_kexec_file_64.c | 12 +++-
 5 files changed, 129 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/ima.h b/arch/powerpc/include/asm/ima.h
index d5a72dd9b499..2313bdface34 100644
--- a/arch/powerpc/include/asm/ima.h
+++ b/arch/powerpc/include/asm/ima.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_POWERPC_IMA_H
 #define _ASM_POWERPC_IMA_H
 
+struct kimage;
+
 int ima_get_kexec_buffer(void **addr, size_t *size);
 int ima_free_kexec_buffer(void);
 
@@ -10,4 +12,18 @@ void remove_ima_buffer(void *fdt, int chosen_node);
 static inline void remove_ima_buffer(void *fdt, int chosen_node) {}
 #endif
 
+#ifdef CONFIG_IMA_KEXEC
+int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
+			      size_t size);
+
+int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node);
+#else
+static inline int setup_ima_buffer(const struct kimage *image, void *fdt,
+				   int chosen_node)
+{
+	remove_ima_buffer(fdt, chosen_node);
+	return 0;
+}
+#endif /* CONFIG_IMA_KEXEC */
+
 #endif /* _ASM_POWERPC_IMA_H */
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
index 23056d2dc330..a49cab287acb 100644
--- a/arch/powerpc/include/asm/kexec.h
+++ b/arch/powerpc/include/asm/kexec.h
@@ -94,12 +94,22 @@ static inline bool kdump_in_progress(void)
 #ifdef CONFIG_KEXEC_FILE
 extern struct kexec_file_ops kexec_elf64_ops;
 
+#ifdef CONFIG_IMA_KEXEC
+#define ARCH_HAS_KIMAGE_ARCH
+
+struct kimage_arch {
+	phys_addr_t ima_buffer_addr;
+	size_t ima_buffer_size;
+};
+#endif
+
 int setup_purgatory(struct kimage *image, const void *slave_code,
 		    const void *fdt, unsigned long kernel_load_addr,
 		    unsigned long fdt_load_addr, unsigned long stack_top,
 		    int debug);
-int setup_new_fdt(void *fdt, unsigned long initrd_load_addr,
-		  unsigned long initrd_len, const char *cmdline);
+int setup_new_fdt(const struct kimage *image, void *fdt,
+		  unsigned long initrd_load_addr, unsigned long initrd_len,
+		  const char *cmdline);
 bool find_debug_console(const void *fdt);
 int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size);
 #endif /* CONFIG_KEXEC_FILE */
diff --git a/arch/powerpc/kernel/ima_kexec.c b/arch/powerpc/kernel/ima_kexec.c
index 36e5a5df3804..5ea42c937ca9 100644
--- a/arch/powerpc/kernel/ima_kexec.c
+++ b/arch/powerpc/kernel/ima_kexec.c
@@ -130,3 +130,94 @@ void remove_ima_buffer(void *fdt, int chosen_node)
 	if (!ret)
 		pr_debug("Removed old IMA buffer reservation.\n");
 }
+
+#ifdef CONFIG_IMA_KEXEC
+/**
+ * arch_ima_add_kexec_buffer - do arch-specific steps to add the IMA buffer
+ *
+ * Architectures should use this function to pass on the IMA buffer
+ * information to the next kernel.
+ *
+ * Return: 0 on success, negative errno on error.
+ */
+int arch_ima_add_kexec_buffer(struct kimage *image, unsigned long load_addr,
+			      size_t size)
+{
+	image->arch.ima_buffer_addr = load_addr;
+	image->arch.ima_buffer_size = size;
+
+	return 0;
+}
+
+static int write_number(void *p, u64 value, int cells)
+{
+	if (cells == 1) {
+		u32 tmp;
+
+		if (value > U32_MAX)
+			return -EINVAL;
+
+		tmp = cpu_to_be32(value);
+		memcpy(p, &tmp, sizeof(tmp));
+	} else if (cells == 2) {
+		u64 tmp;
+
+		tmp = cpu_to_be64(value);
+		memcpy(p, &tmp, sizeof(tmp));
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * setup_ima_buffer - add IMA buffer information to the fdt
+ * @image:		kexec image being loaded.
+ * @fdt:		Flattened device tree for the next kernel.
+ * @chosen_node:	Offset to the chosen node.
+ *
+ * Return: 0 on success, or negative errno on error.
+ */
+int setup_ima_buffer(const struct kimage *image, void *fdt, int chosen_node)
+{
+	int ret, addr_cells, size_cells, entry_size;
+	u8 value[16];
+
+	remove_ima_buffer(fdt, chosen_node);
+	if (!image->arch.ima_buffer_size)
+		return 0;
+
+	ret = get_addr_size_cells(&addr_cells, &size_cells);
+	if (ret)
+		return ret;
+
+	entry_size = 4 * (addr_cells + size_cells);
+
+	if (entry_size > sizeof(value))
+		return -EINVAL;
+
+	ret = write_number(value, image->arch.ima_buffer_addr, addr_cells);
+	if (ret)
+		return ret;
+
+	ret = write_number(value + 4 * addr_cells, image->arch.ima_buffer_size,
+			   size_cells);
+	if (ret)
+		return ret;
+
+	ret = fdt_setprop(fdt, chosen_node, "linux,ima-kexec-buffer", value,
+			  entry_size);
+	if (ret < 0)
+		return -EINVAL;
+
+	ret = fdt_add_mem_rsv(fdt, image->arch.ima_buffer_addr,
+			      image->arch.ima_buffer_size);
+	if (ret)
+		return -EINVAL;
+
+	pr_debug("IMA buffer at 0x%llx, size = 0x%zx\n",
+		 image->arch.ima_buffer_addr, image->arch.ima_buffer_size);
+
+	return 0;
+}
+#endif /* CONFIG_IMA_KEXEC */
diff --git a/arch/powerpc/kernel/kexec_elf_64.c b/arch/powerpc/kernel/kexec_elf_64.c
index dc29e0131b76..1bd1e9865835 100644
--- a/arch/powerpc/kernel/kexec_elf_64.c
+++ b/arch/powerpc/kernel/kexec_elf_64.c
@@ -206,7 +206,7 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
 		goto out;
 	}
 
-	ret = setup_new_fdt(fdt, initrd_load_addr, initrd_len, cmdline);
+	ret = setup_new_fdt(image, fdt, initrd_load_addr, initrd_len, cmdline);
 	if (ret)
 		goto out;
 
diff --git a/arch/powerpc/kernel/machine_kexec_file_64.c b/arch/powerpc/kernel/machine_kexec_file_64.c
index 7b13634f71bf..e4da26dabbaf 100644
--- a/arch/powerpc/kernel/machine_kexec_file_64.c
+++ b/arch/powerpc/kernel/machine_kexec_file_64.c
@@ -393,6 +393,7 @@ int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size)
 
 /*
  * setup_new_fdt - modify /chosen and memory reservation for the next kernel
+ * @image:		kexec image being loaded.
  * @fdt:		Flattened device tree for the next kernel.
  * @initrd_load_addr:	Address where the next initrd will be loaded.
  * @initrd_len:		Size of the next initrd, or 0 if there will be none.
@@ -401,8 +402,9 @@ int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size)
  *
  * Return: 0 on success, or negative errno on error.
  */
-int setup_new_fdt(void *fdt, unsigned long initrd_load_addr,
-		  unsigned long initrd_len, const char *cmdline)
+int setup_new_fdt(const struct kimage *image, void *fdt,
+		  unsigned long initrd_load_addr, unsigned long initrd_len,
+		  const char *cmdline)
 {
 	int ret, chosen_node;
 	const void *prop;
@@ -512,7 +514,11 @@ int setup_new_fdt(void *fdt, unsigned long initrd_load_addr,
 		}
 	}
 
-	remove_ima_buffer(fdt, chosen_node);
+	ret = setup_ima_buffer(image, fdt, chosen_node);
+	if (ret) {
+		pr_err("Error setting up the new device tree.\n");
+		return ret;
+	}
 
 	ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
 	if (ret) {
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:44:57 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:44:57 -0200
Subject: [PATCH v6 09/10] ima: define a canonical binary_runtime_measurements
 list format
In-Reply-To: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017898-10375-10-git-send-email-bauerman@linux.vnet.ibm.com>

From: Mimi Zohar <zohar at linux.vnet.ibm.com>

The IMA binary_runtime_measurements list is currently in platform native
format.

To allow restoring a measurement list carried across kexec with a
different endianness than the targeted kernel, this patch defines
little-endian as the canonical format.  For big endian systems wanting
to save/restore the measurement list from a system with a different
endianness, a new boot command line parameter named "ima_canonical_fmt"
is defined.

Considerations: use of the "ima_canonical_fmt" boot command line
option will break existing userspace applications on big endian systems
expecting the binary_runtime_measurements list to be in platform native
format.

Changelog v3:
- restore PCR value properly

Signed-off-by: Mimi Zohar <zohar at linux.vnet.ibm.com>
---
 Documentation/kernel-parameters.txt       |  4 ++++
 security/integrity/ima/ima.h              |  6 ++++++
 security/integrity/ima/ima_fs.c           | 28 +++++++++++++++++++++-------
 security/integrity/ima/ima_kexec.c        | 11 +++++++++--
 security/integrity/ima/ima_template.c     | 24 ++++++++++++++++++++++--
 security/integrity/ima/ima_template_lib.c |  7 +++++--
 6 files changed, 67 insertions(+), 13 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 37babf91f2cb..3ee81afad7e9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1641,6 +1641,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			The builtin appraise policy appraises all files
 			owned by uid=0.
 
+	ima_canonical_fmt [IMA]
+			Use the canonical format for the binary runtime
+			measurements, instead of host native format.
+
 	ima_hash=	[IMA]
 			Format: { md5 | sha1 | rmd160 | sha256 | sha384
 				   | sha512 | ... }
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 6b0540ad189f..5e6180a4da7d 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -122,6 +122,12 @@ void ima_load_kexec_buffer(void);
 static inline void ima_load_kexec_buffer(void) {}
 #endif /* CONFIG_HAVE_IMA_KEXEC */
 
+/*
+ * The default binary_runtime_measurements list format is defined as the
+ * platform native format.  The canonical format is defined as little-endian.
+ */
+extern bool ima_canonical_fmt;
+
 /* Internal IMA function definitions */
 int ima_init(void);
 int ima_fs_init(void);
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 66e5dd5e226f..2bcad99d434e 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -28,6 +28,16 @@
 
 static DEFINE_MUTEX(ima_write_mutex);
 
+bool ima_canonical_fmt;
+static int __init default_canonical_fmt_setup(char *str)
+{
+#ifdef __BIG_ENDIAN
+	ima_canonical_fmt = 1;
+#endif
+	return 1;
+}
+__setup("ima_canonical_fmt", default_canonical_fmt_setup);
+
 static int valid_policy = 1;
 #define TMPBUFLEN 12
 static ssize_t ima_show_htable_value(char __user *buf, size_t count,
@@ -122,7 +132,7 @@ int ima_measurements_show(struct seq_file *m, void *v)
 	struct ima_queue_entry *qe = v;
 	struct ima_template_entry *e;
 	char *template_name;
-	int namelen;
+	u32 pcr, namelen, template_data_len; /* temporary fields */
 	bool is_ima_template = false;
 	int i;
 
@@ -139,25 +149,29 @@ int ima_measurements_show(struct seq_file *m, void *v)
 	 * PCR used defaults to the same (config option) in
 	 * little-endian format, unless set in policy
 	 */
-	ima_putc(m, &e->pcr, sizeof(e->pcr));
+	pcr = !ima_canonical_fmt ? e->pcr : cpu_to_le32(e->pcr);
+	ima_putc(m, &pcr, sizeof(e->pcr));
 
 	/* 2nd: template digest */
 	ima_putc(m, e->digest, TPM_DIGEST_SIZE);
 
 	/* 3rd: template name size */
-	namelen = strlen(template_name);
+	namelen = !ima_canonical_fmt ? strlen(template_name) :
+		cpu_to_le32(strlen(template_name));
 	ima_putc(m, &namelen, sizeof(namelen));
 
 	/* 4th:  template name */
-	ima_putc(m, template_name, namelen);
+	ima_putc(m, template_name, strlen(template_name));
 
 	/* 5th:  template length (except for 'ima' template) */
 	if (strcmp(template_name, IMA_TEMPLATE_IMA_NAME) == 0)
 		is_ima_template = true;
 
-	if (!is_ima_template)
-		ima_putc(m, &e->template_data_len,
-			 sizeof(e->template_data_len));
+	if (!is_ima_template) {
+		template_data_len = !ima_canonical_fmt ? e->template_data_len :
+			cpu_to_le32(e->template_data_len);
+		ima_putc(m, &template_data_len, sizeof(e->template_data_len));
+	}
 
 	/* 6th:  template specific data */
 	for (i = 0; i < e->template_desc->num_fields; i++) {
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index 2c4824ac1ce1..e473eee913cb 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -21,8 +21,7 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 {
 	struct ima_queue_entry *qe;
 	struct seq_file file;
-	struct ima_kexec_hdr khdr = {
-		.version = 1, .buffer_size = 0, .count = 0};
+	struct ima_kexec_hdr khdr;
 	int ret = 0;
 
 	/* segment size can't change between kexec load and execute */
@@ -36,6 +35,8 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 	file.read_pos = 0;
 	file.count = sizeof(khdr);	/* reserved space */
 
+	memset(&khdr, 0, sizeof(khdr));
+	khdr.version = 1;
 	list_for_each_entry_rcu(qe, &ima_measurements, later) {
 		if (file.count < file.size) {
 			khdr.count++;
@@ -54,7 +55,13 @@ static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
 	 * (eg. version, buffer size, number of measurements)
 	 */
 	khdr.buffer_size = file.count;
+	if (ima_canonical_fmt) {
+		khdr.version = cpu_to_le16(khdr.version);
+		khdr.count = cpu_to_le64(khdr.count);
+		khdr.buffer_size = cpu_to_le64(khdr.buffer_size);
+	}
 	memcpy(file.buf, &khdr, sizeof(khdr));
+
 	print_hex_dump(KERN_DEBUG, "ima dump: ", DUMP_PREFIX_NONE,
 			16, 1, file.buf,
 			file.count < 100 ? file.count : 100, true);
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index e57b4682ff93..004723c4169f 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -304,6 +304,9 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc,
 		}
 		offset += sizeof(field_data->len);
 
+		if (ima_canonical_fmt)
+			field_data->len = le32_to_cpu(field_data->len);
+
 		if (offset > (template_data_size - field_data->len)) {
 			pr_err("Restoring the template field data failed\n");
 			ret = -EINVAL;
@@ -354,7 +357,7 @@ int ima_restore_measurement_list(loff_t size, void *buf)
 	struct binary_data_v1 *data_v1;
 
 	void *bufp = buf + sizeof(*khdr);
-	void *bufendp = buf + khdr->buffer_size;
+	void *bufendp;
 	struct ima_template_entry *entry;
 	struct ima_template_desc *template_desc;
 	unsigned long count = 0;
@@ -363,6 +366,12 @@ int ima_restore_measurement_list(loff_t size, void *buf)
 	if (!buf || size < sizeof(*khdr))
 		return 0;
 
+	if (ima_canonical_fmt) {
+		khdr->version = le16_to_cpu(khdr->version);
+		khdr->count = le64_to_cpu(khdr->count);
+		khdr->buffer_size = le64_to_cpu(khdr->buffer_size);
+	}
+
 	if (khdr->version != 1) {
 		pr_err("attempting to restore a incompatible measurement list");
 		return 0;
@@ -373,6 +382,7 @@ int ima_restore_measurement_list(loff_t size, void *buf)
 	 * v1 format: pcr, digest, template-name-len, template-name,
 	 *	      template-data-size, template-data
 	 */
+	bufendp = buf + khdr->buffer_size;
 	while ((bufp < bufendp) && (count++ < khdr->count)) {
 		if (count > ULONG_MAX - 1) {
 			pr_err("attempting to restore too many measurements");
@@ -380,6 +390,11 @@ int ima_restore_measurement_list(loff_t size, void *buf)
 		}
 
 		hdr_v1 = bufp;
+
+		if (ima_canonical_fmt)
+			hdr_v1->template_name_len =
+			    le32_to_cpu(hdr_v1->template_name_len);
+
 		if ((hdr_v1->template_name_len >= MAX_TEMPLATE_NAME_LEN) ||
 		    ((bufp + hdr_v1->template_name_len) > bufendp)) {
 			pr_err("attempting to restore a template name \
@@ -429,6 +444,10 @@ int ima_restore_measurement_list(loff_t size, void *buf)
 		}
 		bufp += (u_int8_t) sizeof(data_v1->template_data_size);
 
+		if (ima_canonical_fmt)
+			data_v1->template_data_size =
+			    le32_to_cpu(data_v1->template_data_size);
+
 		if (bufp > (bufendp - data_v1->template_data_size)) {
 			pr_err("restoring the template data failed\n");
 			ret = -EINVAL;
@@ -443,7 +462,8 @@ int ima_restore_measurement_list(loff_t size, void *buf)
 			break;
 
 		memcpy(entry->digest, hdr_v1->digest, TPM_DIGEST_SIZE);
-		entry->pcr = hdr_v1->pcr;
+		entry->pcr =
+		    !ima_canonical_fmt ? hdr_v1->pcr : le32_to_cpu(hdr_v1->pcr);
 		ret = ima_restore_measurement_entry(entry);
 		if (ret < 0)
 			break;
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index f9bae04ba176..f9ba37b3928d 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -103,8 +103,11 @@ static void ima_show_template_data_binary(struct seq_file *m,
 	u32 len = (show == IMA_SHOW_BINARY_OLD_STRING_FMT) ?
 	    strlen(field_data->data) : field_data->len;
 
-	if (show != IMA_SHOW_BINARY_NO_FIELD_LEN)
-		ima_putc(m, &len, sizeof(len));
+	if (show != IMA_SHOW_BINARY_NO_FIELD_LEN) {
+		u32 field_len = !ima_canonical_fmt ? len : cpu_to_le32(len);
+
+		ima_putc(m, &field_len, sizeof(field_len));
+	}
 
 	if (!len)
 		return;
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:44:58 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:44:58 -0200
Subject: [PATCH v6 10/10] ima: platform-independent hash value
In-Reply-To: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017898-10375-11-git-send-email-bauerman@linux.vnet.ibm.com>

From: Andreas Steffen <andreas.steffen at strongswan.org>

For remote attestion it is important for the ima measurement values
to be platform-independent. Therefore integer fields to be hashed
must be converted to canonical format.

Changelog:
- Define canonical format as little endian (Mimi)

Signed-off-by: Andreas Steffen <andreas.steffen at strongswan.org>
Signed-off-by: Mimi Zohar <zohar at linux.vnet.ibm.com>
---
 security/integrity/ima/ima_crypto.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 38f2ed830dd6..802d5d20f36f 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -477,11 +477,13 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
 		u8 buffer[IMA_EVENT_NAME_LEN_MAX + 1] = { 0 };
 		u8 *data_to_hash = field_data[i].data;
 		u32 datalen = field_data[i].len;
+		u32 datalen_to_hash =
+		    !ima_canonical_fmt ? datalen : cpu_to_le32(datalen);
 
 		if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) {
 			rc = crypto_shash_update(shash,
-						(const u8 *) &field_data[i].len,
-						sizeof(field_data[i].len));
+						(const u8 *) &datalen_to_hash,
+						sizeof(datalen_to_hash));
 			if (rc)
 				break;
 		} else if (strcmp(td->fields[i]->field_id, "n") == 0) {
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:44:56 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:44:56 -0200
Subject: [PATCH v6 08/10] ima: support restoring multiple template formats
In-Reply-To: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017898-10375-9-git-send-email-bauerman@linux.vnet.ibm.com>

From: Mimi Zohar <zohar at linux.vnet.ibm.com>

The configured IMA measurement list template format can be replaced at
runtime on the boot command line, including a custom template format.
This patch adds support for restoring a measuremement list containing
multiple builtin/custom template formats.

Signed-off-by: Mimi Zohar <zohar at linux.vnet.ibm.com>
---
 security/integrity/ima/ima_template.c | 53 +++++++++++++++++++++++++++++++++--
 1 file changed, 50 insertions(+), 3 deletions(-)

diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index c0d808c20c40..e57b4682ff93 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -155,9 +155,14 @@ static int template_desc_init_fields(const char *template_fmt,
 {
 	const char *template_fmt_ptr;
 	struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX];
-	int template_num_fields = template_fmt_size(template_fmt);
+	int template_num_fields;
 	int i, len;
 
+	if (num_fields && *num_fields > 0) /* already initialized? */
+		return 0;
+
+	template_num_fields = template_fmt_size(template_fmt);
+
 	if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) {
 		pr_err("format string '%s' contains too many fields\n",
 		       template_fmt);
@@ -237,6 +242,35 @@ int __init ima_init_template(void)
 	return result;
 }
 
+static struct ima_template_desc *restore_template_fmt(char *template_name)
+{
+	struct ima_template_desc *template_desc = NULL;
+	int ret;
+
+	ret = template_desc_init_fields(template_name, NULL, NULL);
+	if (ret < 0) {
+		pr_err("attempting to initialize the template \"%s\" failed\n",
+			template_name);
+		goto out;
+	}
+
+	template_desc = kzalloc(sizeof(*template_desc), GFP_KERNEL);
+	if (!template_desc)
+		goto out;
+
+	template_desc->name = "";
+	template_desc->fmt = kstrdup(template_name, GFP_KERNEL);
+	if (!template_desc->fmt)
+		goto out;
+
+	spin_lock(&template_list);
+	list_add_tail_rcu(&template_desc->list, &defined_templates);
+	spin_unlock(&template_list);
+	synchronize_rcu();
+out:
+	return template_desc;
+}
+
 static int ima_restore_template_data(struct ima_template_desc *template_desc,
 				     void *template_data,
 				     int template_data_size,
@@ -367,10 +401,23 @@ int ima_restore_measurement_list(loff_t size, void *buf)
 		}
 		data_v1 = bufp += (u_int8_t)hdr_v1->template_name_len;
 
-		/* get template format */
 		template_desc = lookup_template_desc(template_name);
 		if (!template_desc) {
-			pr_err("template \"%s\" not found\n", template_name);
+			template_desc = restore_template_fmt(template_name);
+			if (!template_desc)
+				break;
+		}
+
+		/*
+		 * Only the running system's template format is initialized
+		 * on boot.  As needed, initialize the other template formats.
+		 */
+		ret = template_desc_init_fields(template_desc->fmt,
+						&(template_desc->fields),
+						&(template_desc->num_fields));
+		if (ret < 0) {
+			pr_err("attempting to restore the template fmt \"%s\" \
+				failed\n", template_desc->fmt);
 			ret = -EINVAL;
 			break;
 		}
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:44:54 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:44:54 -0200
Subject: [PATCH v6 06/10] ima: on soft reboot, save the measurement list
In-Reply-To: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017898-10375-7-git-send-email-bauerman@linux.vnet.ibm.com>

From: Mimi Zohar <zohar at linux.vnet.ibm.com>

The TPM PCRs are only reset on a hard reboot.  In order to validate a
TPM's quote after a soft reboot (eg. kexec -e), the IMA measurement list
of the running kernel must be saved and restored on boot.

This patch uses the kexec buffer passing mechanism to pass the
serialized IMA binary_runtime_measurements to the next kernel.

Changelog v5:
- move writing the IMA measurement list to kexec load and remove
  from kexec execute.
- remove registering notifier to call update on kexec execute
- add includes needed by code in this patch to ima_kexec.c (Thiago)
- fold patch "ima: serialize the binary_runtime_measurements"
into this patch.

Changelog v4:
- Revert the skip_checksum change.??Instead calculate the checksum
with the measurement list segment, on update validate the existing
checksum before re-calulating a new checksum with the updated
measurement list.

Changelog v3:
- Request a kexec segment for storing the measurement list a half page,
not a full page, more than needed for additional measurements.
- Added binary_runtime_size overflow test
- Limit maximum number of pages needed for kexec_segment_size to half
of totalram_pages. (Dave Young)

Changelog v2:
- Fix build issue by defining a stub ima_add_kexec_buffer and stub
  struct kimage when CONFIG_IMA=n and CONFIG_IMA_KEXEC=n. (Fenguang Wu)
- removed kexec_add_handover_buffer() checksum argument.
- added skip_checksum member to kexec_buf
- only register reboot notifier once

Changelog v1:
- updated to call IMA functions  (Mimi)
- move code from ima_template.c to ima_kexec.c (Mimi)

Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
Signed-off-by: Mimi Zohar <zohar at linux.vnet.ibm.com>
Acked-by: "Eric W. Biederman" <ebiederm at xmission.com>
---
 include/linux/ima.h                |  12 ++++
 kernel/kexec_file.c                |   4 ++
 security/integrity/ima/ima.h       |   1 +
 security/integrity/ima/ima_fs.c    |   2 +-
 security/integrity/ima/ima_kexec.c | 117 +++++++++++++++++++++++++++++++++++++
 5 files changed, 135 insertions(+), 1 deletion(-)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 0eb7c2e7f0d6..7f6952f8d6aa 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -11,6 +11,7 @@
 #define _LINUX_IMA_H
 
 #include <linux/fs.h>
+#include <linux/kexec.h>
 struct linux_binprm;
 
 #ifdef CONFIG_IMA
@@ -23,6 +24,10 @@ extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
 			      enum kernel_read_file_id id);
 extern void ima_post_path_mknod(struct dentry *dentry);
 
+#ifdef CONFIG_IMA_KEXEC
+extern void ima_add_kexec_buffer(struct kimage *image);
+#endif
+
 #else
 static inline int ima_bprm_check(struct linux_binprm *bprm)
 {
@@ -62,6 +67,13 @@ static inline void ima_post_path_mknod(struct dentry *dentry)
 
 #endif /* CONFIG_IMA */
 
+#ifndef CONFIG_IMA_KEXEC
+struct kimage;
+
+static inline void ima_add_kexec_buffer(struct kimage *image)
+{}
+#endif
+
 #ifdef CONFIG_IMA_APPRAISE
 extern void ima_inode_post_setattr(struct dentry *dentry);
 extern int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 0c2df7f73792..b56a558e406d 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -19,6 +19,7 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/fs.h>
+#include <linux/ima.h>
 #include <crypto/hash.h>
 #include <crypto/sha.h>
 #include <linux/syscalls.h>
@@ -132,6 +133,9 @@ kimage_file_prepare_segments(struct kimage *image, int kernel_fd, int initrd_fd,
 		return ret;
 	image->kernel_buf_len = size;
 
+	/* IMA needs to pass the measurement list to the next kernel. */
+	ima_add_kexec_buffer(image);
+
 	/* Call arch image probe handlers */
 	ret = arch_kexec_kernel_image_probe(image, image->kernel_buf,
 					    image->kernel_buf_len);
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index ea1dcc452911..139dec67dcbf 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -143,6 +143,7 @@ void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
 struct ima_template_desc *ima_template_desc_current(void);
 int ima_restore_measurement_entry(struct ima_template_entry *entry);
 int ima_restore_measurement_list(loff_t bufsize, void *buf);
+int ima_measurements_show(struct seq_file *m, void *v);
 unsigned long ima_get_binary_runtime_size(void);
 int ima_init_template(void);
 
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index c07a3844ea0a..66e5dd5e226f 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -116,7 +116,7 @@ void ima_putc(struct seq_file *m, void *data, int datalen)
  *       [eventdata length]
  *       eventdata[n]=template specific data
  */
-static int ima_measurements_show(struct seq_file *m, void *v)
+int ima_measurements_show(struct seq_file *m, void *v)
 {
 	/* the list never shrinks, so we don't need a lock here */
 	struct ima_queue_entry *qe = v;
diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c
index 36afd0fe9747..2c4824ac1ce1 100644
--- a/security/integrity/ima/ima_kexec.c
+++ b/security/integrity/ima/ima_kexec.c
@@ -10,8 +10,125 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
+#include <linux/seq_file.h>
+#include <linux/vmalloc.h>
+#include <linux/kexec.h>
 #include "ima.h"
 
+#ifdef CONFIG_IMA_KEXEC
+static int ima_dump_measurement_list(unsigned long *buffer_size, void **buffer,
+				     unsigned long segment_size)
+{
+	struct ima_queue_entry *qe;
+	struct seq_file file;
+	struct ima_kexec_hdr khdr = {
+		.version = 1, .buffer_size = 0, .count = 0};
+	int ret = 0;
+
+	/* segment size can't change between kexec load and execute */
+	file.buf = vmalloc(segment_size);
+	if (!file.buf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	file.size = segment_size;
+	file.read_pos = 0;
+	file.count = sizeof(khdr);	/* reserved space */
+
+	list_for_each_entry_rcu(qe, &ima_measurements, later) {
+		if (file.count < file.size) {
+			khdr.count++;
+			ima_measurements_show(&file, qe);
+		} else {
+			ret = -EINVAL;
+			break;
+		}
+	}
+
+	if (ret < 0)
+		goto out;
+
+	/*
+	 * fill in reserved space with some buffer details
+	 * (eg. version, buffer size, number of measurements)
+	 */
+	khdr.buffer_size = file.count;
+	memcpy(file.buf, &khdr, sizeof(khdr));
+	print_hex_dump(KERN_DEBUG, "ima dump: ", DUMP_PREFIX_NONE,
+			16, 1, file.buf,
+			file.count < 100 ? file.count : 100, true);
+
+	*buffer_size = file.count;
+	*buffer = file.buf;
+out:
+	if (ret == -EINVAL)
+		vfree(file.buf);
+	return ret;
+}
+
+/*
+ * Called during kexec_file_load so that IMA can add a segment to the kexec
+ * image for the measurement list for the next kernel.
+ *
+ * This function assumes that kexec_mutex is held.
+ */
+void ima_add_kexec_buffer(struct kimage *image)
+{
+	struct kexec_buf kbuf = { .image = image, .buf_align = PAGE_SIZE,
+				  .buf_min = 0, .buf_max = ULONG_MAX,
+				  .top_down = true };
+	unsigned long binary_runtime_size;
+
+	/* use more understandable variable names than defined in kbuf */
+	void *kexec_buffer = NULL;
+	size_t kexec_buffer_size;
+	size_t kexec_segment_size;
+	int ret;
+
+	/*
+	 * Reserve an extra half page of memory for additional measurements
+	 * added during the kexec load.
+	 */
+	binary_runtime_size = ima_get_binary_runtime_size();
+	if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE)
+		kexec_segment_size = ULONG_MAX;
+	else
+		kexec_segment_size = ALIGN(ima_get_binary_runtime_size() +
+					   PAGE_SIZE / 2, PAGE_SIZE);
+	if ((kexec_segment_size == ULONG_MAX) ||
+	    ((kexec_segment_size >> PAGE_SHIFT) > totalram_pages / 2)) {
+		pr_err("Binary measurement list too large.\n");
+		return;
+	}
+
+	ima_dump_measurement_list(&kexec_buffer_size, &kexec_buffer,
+				  kexec_segment_size);
+	if (!kexec_buffer) {
+		pr_err("Not enough memory for the kexec measurement buffer.\n");
+		return;
+	}
+
+	kbuf.buffer = kexec_buffer;
+	kbuf.bufsz = kexec_buffer_size;
+	kbuf.memsz = kexec_segment_size;
+	ret = kexec_add_buffer(&kbuf);
+	if (ret) {
+		pr_err("Error passing over kexec measurement buffer.\n");
+		return;
+	}
+
+	ret = arch_ima_add_kexec_buffer(image, kbuf.mem, kexec_segment_size);
+	if (ret) {
+		pr_err("Error passing over kexec measurement buffer.\n");
+		return;
+	}
+
+	pr_debug("kexec measurement buffer for the loaded kernel at 0x%lx.\n",
+		 kbuf.mem);
+}
+#endif /* IMA_KEXEC */
+
 /*
  * Restore the measurement list from the previous kernel.
  */
-- 
2.7.4



From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:44:55 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:44:55 -0200
Subject: [PATCH v6 07/10] ima: store the builtin/custom template definitions
 in a list
In-Reply-To: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017898-10375-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017898-10375-8-git-send-email-bauerman@linux.vnet.ibm.com>

From: Mimi Zohar <zohar at linux.vnet.ibm.com>

The builtin and single custom templates are currently stored in an
array.  In preparation for being able to restore a measurement list
containing multiple builtin/custom templates, this patch stores the
builtin and custom templates as a linked list.  This will permit
defining more than one custom template per boot.

Changelog v4:
- fix "spinlock bad magic" BUG - reported by Dmitry Vyukov

Changelog v3:
- initialize template format list in ima_template_desc_current(), as it
might be called during __setup before normal initialization. (kernel
test robot)
- remove __init annotation of ima_init_template_list()

Changelog v2:
- fix lookup_template_desc() preemption imbalance (kernel test robot)

Signed-off-by: Mimi Zohar <zohar at linux.vnet.ibm.com>
---
 security/integrity/ima/ima.h          |  2 ++
 security/integrity/ima/ima_main.c     |  1 +
 security/integrity/ima/ima_template.c | 52 +++++++++++++++++++++++++++--------
 3 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 139dec67dcbf..6b0540ad189f 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -85,6 +85,7 @@ struct ima_template_field {
 
 /* IMA template descriptor definition */
 struct ima_template_desc {
+	struct list_head list;
 	char *name;
 	char *fmt;
 	int num_fields;
@@ -146,6 +147,7 @@ int ima_restore_measurement_list(loff_t bufsize, void *buf);
 int ima_measurements_show(struct seq_file *m, void *v);
 unsigned long ima_get_binary_runtime_size(void);
 int ima_init_template(void);
+void ima_init_template_list(void);
 
 /*
  * used to protect h_table and sha_table
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 423d111b3b94..50818c60538b 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -418,6 +418,7 @@ static int __init init_ima(void)
 {
 	int error;
 
+	ima_init_template_list();
 	hash_setup(CONFIG_IMA_DEFAULT_HASH);
 	error = ima_init();
 	if (!error) {
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index 37f972cb05fe..c0d808c20c40 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -15,16 +15,20 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/rculist.h>
 #include "ima.h"
 #include "ima_template_lib.h"
 
-static struct ima_template_desc defined_templates[] = {
+static struct ima_template_desc builtin_templates[] = {
 	{.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
 	{.name = "ima-ng", .fmt = "d-ng|n-ng"},
 	{.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
 	{.name = "", .fmt = ""},	/* placeholder for a custom format */
 };
 
+static LIST_HEAD(defined_templates);
+static DEFINE_SPINLOCK(template_list);
+
 static struct ima_template_field supported_fields[] = {
 	{.field_id = "d", .field_init = ima_eventdigest_init,
 	 .field_show = ima_show_template_digest},
@@ -53,6 +57,8 @@ static int __init ima_template_setup(char *str)
 	if (ima_template)
 		return 1;
 
+	ima_init_template_list();
+
 	/*
 	 * Verify that a template with the supplied name exists.
 	 * If not, use CONFIG_IMA_DEFAULT_TEMPLATE.
@@ -81,7 +87,7 @@ __setup("ima_template=", ima_template_setup);
 
 static int __init ima_template_fmt_setup(char *str)
 {
-	int num_templates = ARRAY_SIZE(defined_templates);
+	int num_templates = ARRAY_SIZE(builtin_templates);
 
 	if (ima_template)
 		return 1;
@@ -92,22 +98,28 @@ static int __init ima_template_fmt_setup(char *str)
 		return 1;
 	}
 
-	defined_templates[num_templates - 1].fmt = str;
-	ima_template = defined_templates + num_templates - 1;
+	builtin_templates[num_templates - 1].fmt = str;
+	ima_template = builtin_templates + num_templates - 1;
+
 	return 1;
 }
 __setup("ima_template_fmt=", ima_template_fmt_setup);
 
 static struct ima_template_desc *lookup_template_desc(const char *name)
 {
-	int i;
+	struct ima_template_desc *template_desc;
+	int found = 0;
 
-	for (i = 0; i < ARRAY_SIZE(defined_templates); i++) {
-		if (strcmp(defined_templates[i].name, name) == 0)
-			return defined_templates + i;
+	rcu_read_lock();
+	list_for_each_entry_rcu(template_desc, &defined_templates, list) {
+		if ((strcmp(template_desc->name, name) == 0) ||
+		    (strcmp(template_desc->fmt, name) == 0)) {
+			found = 1;
+			break;
+		}
 	}
-
-	return NULL;
+	rcu_read_unlock();
+	return found ? template_desc : NULL;
 }
 
 static struct ima_template_field *lookup_template_field(const char *field_id)
@@ -183,11 +195,29 @@ static int template_desc_init_fields(const char *template_fmt,
 	return 0;
 }
 
+void ima_init_template_list(void)
+{
+	int i;
+
+	if (!list_empty(&defined_templates))
+		return;
+
+	spin_lock(&template_list);
+	for (i = 0; i < ARRAY_SIZE(builtin_templates); i++) {
+		list_add_tail_rcu(&builtin_templates[i].list,
+				  &defined_templates);
+	}
+	spin_unlock(&template_list);
+	synchronize_rcu();
+}
+
 struct ima_template_desc *ima_template_desc_current(void)
 {
-	if (!ima_template)
+	if (!ima_template) {
+		ima_init_template_list();
 		ima_template =
 		    lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE);
+	}
 	return ima_template;
 }
 
-- 
2.7.4



From ebiederm at xmission.com  Thu Oct 20 22:26:55 2016
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Fri, 21 Oct 2016 00:26:55 -0500
Subject: [PATCH] kexec: Export kexec_in_progress to modules
In-Reply-To: <20161020.215410.650162338407203719.davem@davemloft.net> (David
 Miller's message of "Thu, 20 Oct 2016 21:54:10 -0400 (EDT)")
References: <1477012516-20470-1-git-send-email-f.fainelli@gmail.com>
 <20161020.215410.650162338407203719.davem@davemloft.net>
Message-ID: <871szagtls.fsf@xmission.com>

David Miller <davem at davemloft.net> writes:

> From: Florian Fainelli <f.fainelli at gmail.com>
> Date: Thu, 20 Oct 2016 18:15:16 -0700
>
>> The bcm_sf2 driver uses kexec_in_progress to know whether it can power
>> down an integrated PHY during shutdown, and can be built as a module.
>> Other modules may be using this in the future, so export it.
>> 
>> Fixes: 2399d6143f85 ("net: dsa: bcm_sf2: Prevent GPHY shutdown for kexec'd kernels")
>> Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
>> ---
>> Eric, David, Stephen,
>> 
>> The offending commit is in David's net.git tree, so it would probably make
>> sense to route the fix through the same tree.
>
> Ok, I'll apply this, thanks Florian.

Florian

I am completely confused why any driver would want to do this.

A reboot is semantically identical to a kexec restart.  Always has been.
That is pwoering down your hardware during reboot is not safe.

The only thing that might save you is the hardware reset line being
toggled at which point your hardware is powered up again anyway.

So as far as I can tell you are advocating for a change to support a
driver doing something that is completely pointless.  So no let's not
export this symbol.  Please fix the driver to do something less
pointless instead.

Eric




From bauerman at linux.vnet.ibm.com  Thu Oct 20 19:40:13 2016
From: bauerman at linux.vnet.ibm.com (Thiago Jung Bauermann)
Date: Fri, 21 Oct 2016 00:40:13 -0200
Subject: [PATCH v9 06/10] powerpc: Implement kexec_file_load.
In-Reply-To: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
References: <1477017617-8540-1-git-send-email-bauerman@linux.vnet.ibm.com>
Message-ID: <1477017617-8540-7-git-send-email-bauerman@linux.vnet.ibm.com>

Add arch-specific functions needed by generic kexec_file code.

Also, module_64.c's apply_relocate_add and kexec_file's
arch_kexec_apply_relocations_add have slightly different needs, so
elf64_apply_relocate_add_item needs to be adapted to accommodate both:

When apply_relocate_add is called, the module is already loaded at its
final location in memory so the place where the relocation needs to be
applied and its address in the module's memory are the same.

This is not the case for kexec's purgatory, because it is stored in a
buffer and will only be copied to its final location in memory right
before being executed. Therefore, it needs to be relocated while still
in its buffer. In this case, the place where the relocation needs to
be applied is different from its address in the purgatory's memory.

So we add an address argument to elf64_apply_relocate_add_item
to specify the final address of the relocation in memory. We also add
more relocation types that are used by the purgatory.

Signed-off-by: Josh Sklar <sklar at linux.vnet.ibm.com>
Signed-off-by: Thiago Jung Bauermann <bauerman at linux.vnet.ibm.com>
---
 arch/powerpc/Kconfig                        |  13 ++
 arch/powerpc/include/asm/elf_util.h         |  43 +++++
 arch/powerpc/include/asm/systbl.h           |   1 +
 arch/powerpc/include/asm/unistd.h           |   2 +-
 arch/powerpc/include/uapi/asm/unistd.h      |   1 +
 arch/powerpc/kernel/Makefile                |   1 +
 arch/powerpc/kernel/elf_util.c              |  46 ++++++
 arch/powerpc/kernel/machine_kexec_file_64.c | 245 ++++++++++++++++++++++++++++
 arch/powerpc/kernel/module_64.c             |  71 ++++++--
 9 files changed, 406 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 6cb59c6e5ba4..897d0f14447d 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -455,6 +455,19 @@ config KEXEC
 	  interface is strongly in flux, so no good recommendation can be
 	  made.
 
+config KEXEC_FILE
+	bool "kexec file based system call"
+	select KEXEC_CORE
+	select BUILD_BIN2C
+	depends on PPC64
+	depends on CRYPTO=y
+	depends on CRYPTO_SHA256=y
+	help
+	  This is a new version of the kexec system call. This call is
+	  file based and takes in file descriptors as system call arguments
+	  for kernel and initramfs as opposed to a list of segments as is the
+	  case for the older kexec call.
+
 config RELOCATABLE
 	bool "Build a relocatable kernel"
 	depends on (PPC64 && !COMPILE_TEST) || (FLATMEM && (44x || FSL_BOOKE))
diff --git a/arch/powerpc/include/asm/elf_util.h b/arch/powerpc/include/asm/elf_util.h
new file mode 100644
index 000000000000..1df232f65ec8
--- /dev/null
+++ b/arch/powerpc/include/asm/elf_util.h
@@ -0,0 +1,43 @@
+/*
+ * Utility functions to work with ELF files.
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _ASM_POWERPC_ELF_UTIL_H
+#define _ASM_POWERPC_ELF_UTIL_H
+
+#include <linux/elf.h>
+
+/*
+ * r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
+ * gives the value maximum span in an instruction which uses a signed
+ * offset)
+ */
+static inline unsigned long elf_my_r2(const struct elf_shdr *sechdrs,
+				      unsigned int toc_section)
+{
+	return sechdrs[toc_section].sh_addr + 0x8000;
+}
+
+unsigned int elf_toc_section(const struct elfhdr *ehdr,
+			     const struct elf_shdr *sechdrs);
+
+int elf64_apply_relocate_add_item(const Elf64_Shdr *sechdrs, const char *strtab,
+				  const Elf64_Rela *rela, const Elf64_Sym *sym,
+				  unsigned long *location,
+				  unsigned long address, unsigned long value,
+				  unsigned long my_r2, const char *obj_name,
+				  struct module *me);
+
+#endif /* _ASM_POWERPC_ELF_UTIL_H */
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index 2fc5d4db503c..4b369d83fe9c 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -386,3 +386,4 @@ SYSCALL(mlock2)
 SYSCALL(copy_file_range)
 COMPAT_SYS_SPU(preadv2)
 COMPAT_SYS_SPU(pwritev2)
+SYSCALL(kexec_file_load)
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index cf12c580f6b2..a01e97d3f305 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls		382
+#define NR_syscalls		383
 
 #define __NR__exit __NR_exit
 
diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h
index e9f5f41aa55a..2f26335a3c42 100644
--- a/arch/powerpc/include/uapi/asm/unistd.h
+++ b/arch/powerpc/include/uapi/asm/unistd.h
@@ -392,5 +392,6 @@
 #define __NR_copy_file_range	379
 #define __NR_preadv2		380
 #define __NR_pwritev2		381
+#define __NR_kexec_file_load	382
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 22534a56c914..de14b7eb11bb 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -109,6 +109,7 @@ obj-$(CONFIG_PCI)		+= pci_$(BITS).o $(pci64-y) \
 obj-$(CONFIG_PCI_MSI)		+= msi.o
 obj-$(CONFIG_KEXEC_CORE)	+= machine_kexec.o crash.o \
 				   machine_kexec_$(BITS).o
+obj-$(CONFIG_KEXEC_FILE)	+= machine_kexec_file_$(BITS).o elf_util.o
 obj-$(CONFIG_AUDIT)		+= audit.o
 obj64-$(CONFIG_AUDIT)		+= compat_audit.o
 
diff --git a/arch/powerpc/kernel/elf_util.c b/arch/powerpc/kernel/elf_util.c
new file mode 100644
index 000000000000..ffa68cd6fb99
--- /dev/null
+++ b/arch/powerpc/kernel/elf_util.c
@@ -0,0 +1,46 @@
+/*
+ * Utility functions to work with ELF files.
+ *
+ * Copyright (C) 2016, IBM Corporation
+ *
+ * Based on kexec-tools' kexec-elf.c. Heavily modified for the
+ * kernel by Thiago Jung Bauermann <bauerman at linux.vnet.ibm.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.
+ */
+
+#include <asm/elf_util.h>
+
+/**
+ * elf_toc_section - find the toc section in the file with the given ELF headers
+ * @ehdr:	Pointer to already loaded ELF header.
+ * @sechdrs:	Pointer to already loaded section headers contents.
+ *
+ * Return: TOC section index or 0 if one wasn't found.
+ */
+unsigned int elf_toc_section(const struct elfhdr *ehdr,
+			     const struct elf_shdr *sechdrs)
+{
+	int i;
+	const char *shstrtab;
+
+	/* Section header string table. */
+	shstrtab = (const char *) sechdrs[ehdr->e_shstrndx].sh_offset;
+
+	for (i = 0; i < ehdr->e_shnum; i++) {
+		if (sechdrs[i].sh_size == 0)
+			continue;
+
+		if (!strcmp(&shstrtab[sechdrs[i].sh_name], ".toc"))
+			return i;
+	}
+
+	return 0;
+}
diff --git a/arch/powerpc/kernel/machine_kexec_file_64.c b/arch/powerpc/kernel/machine_kexec_file_64.c
new file mode 100644
index 000000000000..c6b8f75c1624
--- /dev/null
+++ b/arch/powerpc/kernel/machine_kexec_file_64.c
@@ -0,0 +1,245 @@
+/*
+ * ppc64 code to implement the kexec_file_load syscall
+ *
+ * Copyright (C) 2004  Adam Litke (agl at us.ibm.com)
+ * Copyright (C) 2004  IBM Corp.
+ * Copyright (C) 2005  R Sharada (sharada at in.ibm.com)
+ * Copyright (C) 2006  Mohan Kumar M (mohan at in.ibm.com)
+ * Copyright (C) 2016  IBM Corporation
+ *
+ * Based on kexec-tools' kexec-elf-ppc64.c.
+ * Heavily modified for the kernel by
+ * Thiago Jung Bauermann <bauerman at linux.vnet.ibm.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.
+ */
+
+#include <linux/slab.h>
+#include <linux/kexec.h>
+#include <linux/memblock.h>
+#include <linux/libfdt.h>
+#include <asm/elf_util.h>
+
+#define SLAVE_CODE_SIZE		256
+
+static struct kexec_file_ops *kexec_file_loaders[] = { };
+
+int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
+				  unsigned long buf_len)
+{
+	int i, ret = -ENOEXEC;
+	struct kexec_file_ops *fops;
+
+	/* We don't support crash kernels yet. */
+	if (image->type == KEXEC_TYPE_CRASH)
+		return -ENOTSUPP;
+
+	for (i = 0; i < ARRAY_SIZE(kexec_file_loaders); i++) {
+		fops = kexec_file_loaders[i];
+		if (!fops || !fops->probe)
+			continue;
+
+		ret = fops->probe(buf, buf_len);
+		if (!ret) {
+			image->fops = fops;
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+void *arch_kexec_kernel_image_load(struct kimage *image)
+{
+	if (!image->fops || !image->fops->load)
+		return ERR_PTR(-ENOEXEC);
+
+	return image->fops->load(image, image->kernel_buf,
+				 image->kernel_buf_len, image->initrd_buf,
+				 image->initrd_buf_len, image->cmdline_buf,
+				 image->cmdline_buf_len);
+}
+
+int arch_kimage_file_post_load_cleanup(struct kimage *image)
+{
+	if (!image->fops || !image->fops->cleanup)
+		return 0;
+
+	return image->fops->cleanup(image->image_loader_data);
+}
+
+/**
+ * arch_kexec_walk_mem - call func(data) for each unreserved memory block
+ * @kbuf:	Context info for the search. Also passed to @func.
+ * @func:	Function to call for each memory block.
+ *
+ * This function is used by kexec_add_buffer and kexec_locate_mem_hole
+ * to find unreserved memory to load kexec segments into.
+ *
+ * Return: The memory walk will stop when func returns a non-zero value
+ * and that value will be returned. If all free regions are visited without
+ * func returning non-zero, then zero will be returned.
+ */
+int arch_kexec_walk_mem(struct kexec_buf *kbuf, int (*func)(u64, u64, void *))
+{
+	int ret = 0;
+	u64 i;
+	phys_addr_t mstart, mend;
+
+	if (kbuf->top_down) {
+		for_each_free_mem_range_reverse(i, NUMA_NO_NODE, 0,
+						&mstart, &mend, NULL) {
+			/*
+			 * In memblock, end points to the first byte after the
+			 * range while in kexec, end points to the last byte
+			 * in the range.
+			 */
+			ret = func(mstart, mend - 1, kbuf);
+			if (ret)
+				break;
+		}
+	} else {
+		for_each_free_mem_range(i, NUMA_NO_NODE, 0, &mstart, &mend,
+					NULL) {
+			/*
+			 * In memblock, end points to the first byte after the
+			 * range while in kexec, end points to the last byte
+			 * in the range.
+			 */
+			ret = func(mstart, mend - 1, kbuf);
+			if (ret)
+				break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * arch_kexec_apply_relocations_add - apply purgatory relocations
+ * @ehdr:	Pointer to ELF headers.
+ * @sechdrs:	Pointer to section headers.
+ * @relsec:	Section index of SHT_RELA section.
+ *
+ * Elf64_Shdr.sh_offset has been modified to keep the pointer to the section
+ * contents, while Elf64_Shdr.sh_addr points to the final address of the
+ * section in memory.
+ */
+int arch_kexec_apply_relocations_add(const Elf64_Ehdr *ehdr,
+				     Elf64_Shdr *sechdrs, unsigned int relsec)
+{
+	unsigned int i;
+	int ret;
+	int reloc_type;
+	unsigned long *location;
+	unsigned long address;
+	unsigned long value;
+	const char *name;
+	Elf64_Sym *sym;
+	/* Section containing the relocation entries. */
+	Elf64_Shdr *rel_section = &sechdrs[relsec];
+	const Elf64_Rela *rela = (const Elf64_Rela *) rel_section->sh_offset;
+	/* Section to which relocations apply. */
+	Elf64_Shdr *target_section = &sechdrs[rel_section->sh_info];
+	/* Associated symbol table. */
+	Elf64_Shdr *symtabsec = &sechdrs[rel_section->sh_link];
+	void *syms_base = (void *) symtabsec->sh_offset;
+	void *loc_base = (void *) target_section->sh_offset;
+	Elf64_Addr addr_base = target_section->sh_addr;
+	unsigned long sec_base;
+	unsigned long r2;
+	unsigned int toc;
+	const char *strtab;
+
+	if (symtabsec->sh_link >= ehdr->e_shnum) {
+		/* Invalid strtab section number */
+		pr_err("Invalid string table section index %d\n",
+		       symtabsec->sh_link);
+		return -ENOEXEC;
+	}
+
+	toc = elf_toc_section(ehdr, sechdrs);
+	if (!toc) {
+		pr_err("Purgatory TOC section not found.");
+		return -ENOEXEC;
+	}
+
+	r2 = elf_my_r2(sechdrs, toc);
+
+	/* String table for the associated symbol table. */
+	strtab = (const char *) sechdrs[symtabsec->sh_link].sh_offset;
+
+	for (i = 0; i < rel_section->sh_size / sizeof(Elf64_Rela); i++) {
+		/*
+		 * rels[i].r_offset contains the byte offset from the beginning
+		 * of section to the storage unit affected.
+		 *
+		 * This is the location to update in the temporary buffer where
+		 * the section is currently loaded. The section will finally
+		 * be loaded to a different address later, pointed to by
+		 * addr_base.
+		 */
+		location = loc_base + rela[i].r_offset;
+
+		/* Final address of the location. */
+		address = addr_base + rela[i].r_offset;
+
+		/* This is the symbol the relocation is referring to. */
+		sym = (Elf64_Sym *) syms_base + ELF64_R_SYM(rela[i].r_info);
+
+		if (sym->st_name)
+			name = strtab + sym->st_name;
+		else
+			name = "<unnamed symbol>";
+
+		reloc_type = ELF64_R_TYPE(rela[i].r_info);
+
+		pr_debug("RELOC at %p: %i-type as %s (0x%lx) + %li\n",
+		       location, reloc_type, name, (unsigned long)sym->st_value,
+		       (long)rela[i].r_addend);
+
+		/*
+		 * TOC symbols appear as undefined but should be
+		 * resolved as well, so allow them to be processed.
+		 */
+		if (sym->st_shndx == SHN_UNDEF && strcmp(name, ".TOC.") != 0 &&
+				reloc_type != R_PPC64_TOC) {
+			pr_err("Undefined symbol: %s\n", name);
+			return -ENOEXEC;
+		} else if (sym->st_shndx == SHN_COMMON) {
+			pr_err("Symbol '%s' in common section.\n",
+			       name);
+			return -ENOEXEC;
+		}
+
+		if (sym->st_shndx != SHN_ABS) {
+			if (sym->st_shndx >= ehdr->e_shnum) {
+				pr_err("Invalid section %d for symbol %s\n",
+				       sym->st_shndx, name);
+				return -ENOEXEC;
+			}
+
+			sec_base = sechdrs[sym->st_shndx].sh_addr;
+		} else
+			sec_base = 0;
+
+		/* `Everything is relative'. */
+		value = sym->st_value + sec_base + rela[i].r_addend;
+
+		ret = elf64_apply_relocate_add_item(sechdrs, strtab, &rela[i],
+						    sym, location, address,
+						    value, r2,
+						    "kexec purgatory", NULL);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 61baad036639..8307cf2f07bf 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -507,15 +507,12 @@ static int restore_r2(u32 *instruction, struct module *me)
 	return 1;
 }
 
-static int elf64_apply_relocate_add_item(const Elf64_Shdr *sechdrs,
-					 const char *strtab,
-					 const Elf64_Rela *rela,
-					 const Elf64_Sym *sym,
-					 unsigned long *location,
-					 unsigned long value,
-					 unsigned long my_r2,
-					 const char *obj_name,
-					 struct module *me)
+int elf64_apply_relocate_add_item(const Elf64_Shdr *sechdrs, const char *strtab,
+				  const Elf64_Rela *rela, const Elf64_Sym *sym,
+				  unsigned long *location,
+				  unsigned long address, unsigned long value,
+				  unsigned long my_r2, const char *obj_name,
+				  struct module *me)
 {
 	switch (ELF64_R_TYPE(rela->r_info)) {
 	case R_PPC64_ADDR32:
@@ -588,9 +585,32 @@ static int elf64_apply_relocate_add_item(const Elf64_Shdr *sechdrs,
 			| (value & 0xffff);
 		break;
 
+	case R_PPC64_REL14:
+		/* Convert value to relative */
+		value -= address;
+		if (value + 0x8000 > 0xffff || (value & 3) != 0) {
+			pr_err("%s: REL14 %li out of range!\n",
+			       obj_name, (long int) value);
+			return -ENOEXEC;
+		}
+
+		/* Only replace bits 2 through 16 */
+		*(uint32_t *)location
+			= (*(uint32_t *)location & ~0xfffc)
+			| (value & 0xfffc);
+		break;
+
 	case R_PPC_REL24:
 		/* FIXME: Handle weak symbols here --RR */
 		if (sym->st_shndx == SHN_UNDEF) {
+			/*
+			 * The purgatory relocation code passes NULL for me,
+			 * but the purgatory doesn't have any REL24 relocations
+			 * for undefined symbols, so if this happens it's a bug.
+			 */
+			if (WARN_ON(!me))
+				return -ENOEXEC;
+
 			/* External: go via stub */
 			value = stub_for_addr(sechdrs, value, me);
 			if (!value)
@@ -603,7 +623,7 @@ static int elf64_apply_relocate_add_item(const Elf64_Shdr *sechdrs,
 			value += local_entry_offset(sym);
 
 		/* Convert value to relative */
-		value -= (unsigned long)location;
+		value -= address;
 		if (value + 0x2000000 > 0x3ffffff || (value & 3) != 0) {
 			pr_err("%s: REL24 %li out of range!\n",
 			       obj_name, (long int)value);
@@ -618,7 +638,7 @@ static int elf64_apply_relocate_add_item(const Elf64_Shdr *sechdrs,
 
 	case R_PPC64_REL64:
 		/* 64 bits relative (used by features fixups) */
-		*location = value - (unsigned long)location;
+		*location = value - address;
 		break;
 
 	case R_PPC64_TOCSAVE:
@@ -634,7 +654,7 @@ static int elf64_apply_relocate_add_item(const Elf64_Shdr *sechdrs,
 		 * Optimize ELFv2 large code model entry point if
 		 * the TOC is within 2GB range of current location.
 		 */
-		value = my_r2 - (unsigned long)location;
+		value = my_r2 - address;
 		if (value + 0x80008000 > 0xffffffff)
 			break;
 		/*
@@ -656,9 +676,27 @@ static int elf64_apply_relocate_add_item(const Elf64_Shdr *sechdrs,
 		((uint32_t *)location)[1] = 0x38420000 + PPC_LO(value);
 		break;
 
+	case R_PPC64_ADDR16_LO:
+		*(uint16_t *)location = value & 0xffff;
+		break;
+
+	case R_PPC64_ADDR16_HI:
+		*(uint16_t *)location = (value >> 16) & 0xffff;
+		break;
+
+	case R_PPC64_ADDR16_HIGHER:
+		*(uint16_t *)location = (((uint64_t)value >> 32) &
+						0xffff);
+		break;
+
+	case R_PPC64_ADDR16_HIGHEST:
+		*(uint16_t *)location = (((uint64_t)value >> 48) &
+						0xffff);
+		break;
+
 	case R_PPC64_REL16_HA:
 		/* Subtract location pointer */
-		value -= (unsigned long)location;
+		value -= address;
 		value = ((value + 0x8000) >> 16);
 		*((uint16_t *) location)
 			= (*((uint16_t *) location) & ~0xffff)
@@ -667,7 +705,7 @@ static int elf64_apply_relocate_add_item(const Elf64_Shdr *sechdrs,
 
 	case R_PPC64_REL16_LO:
 		/* Subtract location pointer */
-		value -= (unsigned long)location;
+		value -= address;
 		*((uint16_t *) location)
 			= (*((uint16_t *) location) & ~0xffff)
 			| (value & 0xffff);
@@ -725,8 +763,9 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
 		value = sym->st_value + rela[i].r_addend;
 
 		ret = elf64_apply_relocate_add_item(sechdrs, strtab, &rela[i],
-						    sym, location, value,
-						    my_r2(sechdrs, me),
+						    sym, location,
+						    (unsigned long) location,
+						    value, my_r2(sechdrs, me),
 						    me->name, me);
 		if (ret)
 			return ret;
-- 
2.7.4



From davem at davemloft.net  Fri Oct 21 07:13:43 2016
From: davem at davemloft.net (David Miller)
Date: Fri, 21 Oct 2016 10:13:43 -0400 (EDT)
Subject: [PATCH] kexec: Export kexec_in_progress to modules
In-Reply-To: <871szagtls.fsf@xmission.com>
References: <1477012516-20470-1-git-send-email-f.fainelli@gmail.com>
 <20161020.215410.650162338407203719.davem@davemloft.net>
 <871szagtls.fsf@xmission.com>
Message-ID: <20161021.101343.1389577512803674816.davem@davemloft.net>

From: ebiederm at xmission.com (Eric W. Biederman)
Date: Fri, 21 Oct 2016 00:26:55 -0500

> So as far as I can tell you are advocating for a change to support a
> driver doing something that is completely pointless.  So no let's not
> export this symbol.  Please fix the driver to do something less
> pointless instead.

FLorian explained his reasoning for doing what he is doing in this
specific driver and it made sense to me.


From geoff at infradead.org  Fri Oct 21 10:05:26 2016
From: geoff at infradead.org (Geoff Levand)
Date: Fri, 21 Oct 2016 10:05:26 -0700
Subject: [PATCH] kexec: Increase the upper limit for RAM segments
In-Reply-To: <1477005268-26943-1-git-send-email-sgoel@codeaurora.org>
References: <1477005268-26943-1-git-send-email-sgoel@codeaurora.org>
Message-ID: <cad5f084-b914-f522-eb43-71ed8a45b2a0@infradead.org>

Hi Sameer.

On 10/20/2016 04:14 PM, Sameer Goel wrote:
> Change the current hardcoded values to 64 from 16.

Please add an explanation of why this change is needed.

-Geoff


From ebiederm at xmission.com  Fri Oct 21 11:37:26 2016
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Fri, 21 Oct 2016 13:37:26 -0500
Subject: [PATCH] kexec: Export kexec_in_progress to modules
In-Reply-To: <20161021.101343.1389577512803674816.davem@davemloft.net> (David
 Miller's message of "Fri, 21 Oct 2016 10:13:43 -0400 (EDT)")
References: <1477012516-20470-1-git-send-email-f.fainelli@gmail.com>
 <20161020.215410.650162338407203719.davem@davemloft.net>
 <871szagtls.fsf@xmission.com>
 <20161021.101343.1389577512803674816.davem@davemloft.net>
Message-ID: <87wph1eeft.fsf@xmission.com>

David Miller <davem at davemloft.net> writes:

> From: ebiederm at xmission.com (Eric W. Biederman)
> Date: Fri, 21 Oct 2016 00:26:55 -0500
>
>> So as far as I can tell you are advocating for a change to support a
>> driver doing something that is completely pointless.  So no let's not
>> export this symbol.  Please fix the driver to do something less
>> pointless instead.
>
> FLorian explained his reasoning for doing what he is doing in this
> specific driver and it made sense to me.

What doesn't make sense to me is not doing that for any other kind of
reboot.

Of the 3 uses of kexec_in_progres in the kernel (not counting this one)
I think there is only one of them that is really valid.   And that one
is only valid because it is the least horrible thing the pci layer can
do.  (AKA it is a hack even there).

It really is nonsense having methods do different things depending on
context and that is why kexec_in_progress is not exeported.

As far as I can tell the use of kexec_in_progress winds up being
a fragile hack that will just cause more problems later on.

Florian is there a good readon why you don't just do?

static void bcm_sf2_sw_shutdown(struct platform_device *pdev)
{
        struct bcm_sf2_priv *priv = platform_get_drvdata(pdev);

	/* For a kernel about to be kexec'd we want to keep the GPHY on for a
         * successful MDIO bus scan to occur. If we did turn off the GPHY
	 * before (e.g: port_disable), this will also power it back on.
	 */
	if (priv->hw_params.num_gphy == 1)
		bcm_sf2_gphy_enable_set(priv->dev->ds, true);
}

I certainly don't see anything in the changelog to explain why that
isn't done.

Eric



From f.fainelli at gmail.com  Fri Oct 21 11:48:24 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 21 Oct 2016 11:48:24 -0700
Subject: [PATCH] kexec: Export kexec_in_progress to modules
In-Reply-To: <87wph1eeft.fsf@xmission.com>
References: <1477012516-20470-1-git-send-email-f.fainelli@gmail.com>
 <20161020.215410.650162338407203719.davem@davemloft.net>
 <871szagtls.fsf@xmission.com>
 <20161021.101343.1389577512803674816.davem@davemloft.net>
 <87wph1eeft.fsf@xmission.com>
Message-ID: <441f79c2-fcf3-b35b-f30d-3667513a51c0@gmail.com>

On 10/21/2016 11:37 AM, Eric W. Biederman wrote:
> David Miller <davem at davemloft.net> writes:
> 
>> From: ebiederm at xmission.com (Eric W. Biederman)
>> Date: Fri, 21 Oct 2016 00:26:55 -0500
>>
>>> So as far as I can tell you are advocating for a change to support a
>>> driver doing something that is completely pointless.  So no let's not
>>> export this symbol.  Please fix the driver to do something less
>>> pointless instead.
>>
>> FLorian explained his reasoning for doing what he is doing in this
>> specific driver and it made sense to me.
> 
> What doesn't make sense to me is not doing that for any other kind of
> reboot.
> 
> Of the 3 uses of kexec_in_progres in the kernel (not counting this one)
> I think there is only one of them that is really valid.   And that one
> is only valid because it is the least horrible thing the pci layer can
> do.  (AKA it is a hack even there).
> 
> It really is nonsense having methods do different things depending on
> context and that is why kexec_in_progress is not exeported.
> 
> As far as I can tell the use of kexec_in_progress winds up being
> a fragile hack that will just cause more problems later on.
> 
> Florian is there a good readon why you don't just do?

Checking kexec_in_progress allowed not to turn the PHY on for a normal
reboot case, since we don't necessarily know when it will be
re-initialized next, so in that sense it's a power optimization that is
nice to have.

> 
> static void bcm_sf2_sw_shutdown(struct platform_device *pdev)
> {
>         struct bcm_sf2_priv *priv = platform_get_drvdata(pdev);
> 
> 	/* For a kernel about to be kexec'd we want to keep the GPHY on for a
>          * successful MDIO bus scan to occur. If we did turn off the GPHY
> 	 * before (e.g: port_disable), this will also power it back on.
> 	 */
> 	if (priv->hw_params.num_gphy == 1)
> 		bcm_sf2_gphy_enable_set(priv->dev->ds, true);
> }
> 
> I certainly don't see anything in the changelog to explain why that
> isn't done.

That would result in an identical behavior for what I am after, David,
shall I send a revert plus this?
-- 
Florian


From f.fainelli at gmail.com  Fri Oct 21 14:21:54 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 21 Oct 2016 14:21:54 -0700
Subject: [PATCH net 0/2] net: dsa: bcm_sf2: Do not rely on kexec_in_progress
Message-ID: <1477084916-26327-1-git-send-email-f.fainelli@gmail.com>

David, Eric,

These are the two patches following the discussing we had on kexec_in_progress.

Feel free to apply or discard them, thanks!

Florian Fainelli (2):
  Revert "kexec: Export kexec_in_progress to modules"
  net: dsa: bcm_sf2: Do not rely on kexec_in_progress

 drivers/net/dsa/bcm_sf2.c | 5 +++--
 kernel/kexec_core.c       | 1 -
 2 files changed, 3 insertions(+), 3 deletions(-)

-- 
2.7.4



From f.fainelli at gmail.com  Fri Oct 21 14:21:55 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 21 Oct 2016 14:21:55 -0700
Subject: [PATCH net 1/2] Revert "kexec: Export kexec_in_progress to modules"
In-Reply-To: <1477084916-26327-1-git-send-email-f.fainelli@gmail.com>
References: <1477084916-26327-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1477084916-26327-2-git-send-email-f.fainelli@gmail.com>

This reverts commit 97dcaa0fcfd24daa9a36c212c1ad1d5a97759212. Based on
the review discussion with Eric, we will come up with a different fix
for the bcm_sf2 driver which does not make it rely on the
kexec_in_progress value.

Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 kernel/kexec_core.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 786ab85a5452..561675589511 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -59,7 +59,6 @@ size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
 
 /* Flag to indicate we are going to kexec a new kernel */
 bool kexec_in_progress = false;
-EXPORT_SYMBOL_GPL(kexec_in_progress);
 
 
 /* Location of the reserved area for the crash kernel */
-- 
2.7.4



From f.fainelli at gmail.com  Fri Oct 21 14:21:56 2016
From: f.fainelli at gmail.com (Florian Fainelli)
Date: Fri, 21 Oct 2016 14:21:56 -0700
Subject: [PATCH net 2/2] net: dsa: bcm_sf2: Do not rely on kexec_in_progress
In-Reply-To: <1477084916-26327-1-git-send-email-f.fainelli@gmail.com>
References: <1477084916-26327-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <1477084916-26327-3-git-send-email-f.fainelli@gmail.com>

After discussing with Eric, it turns out that, while using
kexec_in_progress is a nice optimization, which prevents us from always
powering on the integrated PHY, let's just turn it on in the shutdown
path.

This removes a dependency on kexec_in_progress which, according to Eric
should not be used by modules

Fixes: 2399d6143f85 ("net: dsa: bcm_sf2: Prevent GPHY shutdown for kexec'd kernels")
Signed-off-by: Florian Fainelli <f.fainelli at gmail.com>
---
 drivers/net/dsa/bcm_sf2.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 077a24541584..e3ee27ce13dd 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -30,7 +30,6 @@
 #include <linux/etherdevice.h>
 #include <net/switchdev.h>
 #include <linux/platform_data/b53.h>
-#include <linux/kexec.h>
 
 #include "bcm_sf2.h"
 #include "bcm_sf2_regs.h"
@@ -1141,9 +1140,11 @@ static void bcm_sf2_sw_shutdown(struct platform_device *pdev)
 	/* For a kernel about to be kexec'd we want to keep the GPHY on for a
 	 * successful MDIO bus scan to occur. If we did turn off the GPHY
 	 * before (e.g: port_disable), this will also power it back on.
+	 *
+	 * Do not rely on kexec_in_progress, just power the PHY on.
 	 */
 	if (priv->hw_params.num_gphy == 1)
-		bcm_sf2_gphy_enable_set(priv->dev->ds, kexec_in_progress);
+		bcm_sf2_gphy_enable_set(priv->dev->ds, true);
 }
 
 #ifdef CONFIG_PM_SLEEP
-- 
2.7.4



From ville.syrjala at linux.intel.com  Fri Oct 21 19:18:04 2016
From: ville.syrjala at linux.intel.com (ville.syrjala at linux.intel.com)
Date: Sat, 22 Oct 2016 05:18:04 +0300
Subject: [PATCH] arch/x86: Don't try to poke disabled/non-existent APIC
Message-ID: <1477102684-5092-1-git-send-email-ville.syrjala@linux.intel.com>

From: Ville Syrj?l? <ville.syrjala at linux.intel.com>

Apparently trying to poke a disabled or non-existent APIC
leads to a box that doesn't even boot. Let's not do that.

No real clue if this is the right fix, but at least my
P3 machine boots again.

Cc: stable at vger.kernel.org
Cc: Ingo Molnar <mingo at redhat.com>
Cc: "H. Peter Anvin" <hpa at zytor.com>
Cc: x86 at kernel.org
Cc: Prarit Bhargava <prarit at redhat.com>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Len Brown <len.brown at intel.com>
Cc: Borislav Petkov <bp at suse.de>
Cc: Andi Kleen <ak at linux.intel.com>
Cc: Jiri Olsa <jolsa at redhat.com>
Cc: Juergen Gross <jgross at suse.com>
Cc: dyoung at redhat.com
Cc: Eric Biederman <ebiederm at xmission.com>
Cc: kexec at lists.infradead.org
Cc: Thomas Gleixner <tglx at linutronix.de>
Fixes: 2a51fe083eba ("arch/x86: Handle non enumerated CPU after physical hotplug")
Signed-off-by: Ville Syrj?l? <ville.syrjala at linux.intel.com>
---
 arch/x86/kernel/smpboot.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 951f093a96fe..42f5eb7b4f6c 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1409,15 +1409,17 @@ __init void prefill_possible_map(void)
 
 	/* No boot processor was found in mptable or ACPI MADT */
 	if (!num_processors) {
-		int apicid = boot_cpu_physical_apicid;
-		int cpu = hard_smp_processor_id();
+		if (boot_cpu_has(X86_FEATURE_APIC)) {
+			int apicid = boot_cpu_physical_apicid;
+			int cpu = hard_smp_processor_id();
 
-		pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu);
+			pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu);
 
-		/* Make sure boot cpu is enumerated */
-		if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
-		    apic->apic_id_valid(apicid))
-			generic_processor_info(apicid, boot_cpu_apic_version);
+			/* Make sure boot cpu is enumerated */
+			if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
+			    apic->apic_id_valid(apicid))
+				generic_processor_info(apicid, boot_cpu_apic_version);
+		}
 
 		if (!num_processors)
 			num_processors = 1;
-- 
2.7.4



From davem at davemloft.net  Sat Oct 22 13:18:16 2016
From: davem at davemloft.net (David Miller)
Date: Sat, 22 Oct 2016 16:18:16 -0400 (EDT)
Subject: [PATCH net 0/2] net: dsa: bcm_sf2: Do not rely on
 kexec_in_progress
In-Reply-To: <1477084916-26327-1-git-send-email-f.fainelli@gmail.com>
References: <1477084916-26327-1-git-send-email-f.fainelli@gmail.com>
Message-ID: <20161022.161816.874616377296105622.davem@davemloft.net>

From: Florian Fainelli <f.fainelli at gmail.com>
Date: Fri, 21 Oct 2016 14:21:54 -0700

> These are the two patches following the discussing we had on
> kexec_in_progress.
> 
> Feel free to apply or discard them, thanks!

Applied, thanks.


From ctfd at performancewisp.com  Sun Oct 23 05:22:19 2016
From: ctfd at performancewisp.com (Gill Deirdre)
Date: Sun, 23 Oct 2016 20:22:19 +0800
Subject: Email
Message-ID: b73c5bdf075cfeb22cce3be1f08869b3

Your email won ?4,000,000.00 El Gordo (First Prize) in the End of year Spanish Christmas Lottery Bonanza 2016 (Loter?a de Navidad). Contact spanishlottery2016 at rogers.com to claim.


From ctfd at performancewisp.com  Sun Oct 23 08:05:19 2016
From: ctfd at performancewisp.com (Gill Deirdre)
Date: Sun, 23 Oct 2016 23:05:19 +0800
Subject: Donation
Message-ID: be1dcb9e90f69694bb6f04dffdc1bb85

Hello, My name is Gloria C. Mackenzie, i have a Monetary Donation to make for less privilege and yourself and your organization, am writing you with a friend's email, please contact me on gloriacmackenzie07 at rogers.com


From smith.not.western at gmail.com  Mon Oct 24 07:42:45 2016
From: smith.not.western at gmail.com (Simon T)
Date: Mon, 24 Oct 2016 15:42:45 +0100
Subject: kexec and arm64 advice
Message-ID: <CAKYm0coteEEapCNwmj+KmGd57C_C3--nXQfjyD_FLoGXSkqMkQ@mail.gmail.com>

Hi,

I'm trying to get kexec working on a cross-compiled arm64/aarch64
system, using Linux kernel 4.4.23. I'm using kexec-tool's master
branch (commit e345e27417db00a9e754ca0ca14b2ec87d0552f7 from
https://git.kernel.org/cgit/linux/kernel/git/geoff/kexec-tools.git). I
initially tried using the patches for linux-kexec's kexec-13 branch
with manual massaging in some spots because kexec-13 is for 4.4.0 not
4.4.23. Both tools and kernel appear to build fine, however when it
comes time to kexec, I encounter this message: "kexec_load failed:
Function not implemented"

Searching through the patches, I don't find any reference to kexec_load itself.

Should I be applying a different version of kexec-tools, or
linux-kexec patches, to my build? (I'm restricted to 4.4.23 as the
base kernel)

Is there a way post compile to check if the kexec_load function is
implemented, aside from actually deploying the image and calling
kexec? I've run strings against the Image but it doesn't give an exact
match for kexec_load (see below).

Anything else I should be looking at?

# kexec -l /mnt/target/boot/vmlinux --initrd=/tmp/root.sfs
Modified cmdline:root=/dev/mmcblk0p2
Unable to find /proc/device-tree/chosen/[linux,]stdout-path, printing
from purgatory is disabled
kexec_load failed: Function not implemented
entry       = 0x8095f000 flags = 0xb70000
nr_segments = 4
segment[0].buf   = 0x7fa0f64010
segment[0].bufsz = 0x7fbc00
segment[0].mem   = 0x80080000
segment[0].memsz = 0x8d0000
segment[1].buf   = 0x20cc0830
segment[1].bufsz = 0xe515
segment[1].mem   = 0x80950000
segment[1].memsz = 0xf000
segment[2].buf   = 0x20ccf840
segment[2].bufsz = 0x6080
segment[2].mem   = 0x8095f000
segment[2].memsz = 0x7000
segment[3].buf   = 0x7f9e843010
segment[3].bufsz = 0x2720000
segment[3].mem   = 0xc0000000
segment[3].memsz = 0x2720000

(I've also tried kexec -l with boot/Image instead of boot/vmlinux)

$ grep -i kexec .config
CONFIG_KERNEL_KEXEC=y
CONFIG_PACKAGE_kexec-tools=y
CONFIG_KEXEC_TOOLS_TARGET_NAME="aarch64"
# CONFIG_KEXEC_TOOLS_kdump is not set
CONFIG_KEXEC_ZLIB=y
# CONFIG_KEXEC_LZMA is not set

$ strings <build_dir>/arch/arm64/boot/Image  | grep kexec_load
Wcompat_sys_kexec_load
Wsys_kexec_load

Thanks!

Simon


From louis.bouchard at canonical.com  Mon Oct 24 07:54:02 2016
From: louis.bouchard at canonical.com (Louis Bouchard)
Date: Mon, 24 Oct 2016 16:54:02 +0200
Subject: makedumpfile issues many readpage_elf: Attempt to read
 non-existent page
In-Reply-To: <57ED187D.3040007@canonical.com>
References: <57E3DCDB.5020308@canonical.com>
 <0910DD04CBD6DE4193FCF86B9C00BE9701E6B42E@BPXM01GP.gisp.nec.co.jp>
 <57ED187D.3040007@canonical.com>
Message-ID: <CAL0thcP2Pp43nWLJ_jfwDQnW4RNRpP27fpymQ8pPtORPaeX8nQ@mail.gmail.com>

Hello,

Le 29/09/2016 ? 15:34, Louis Bouchard a ?crit :
> Hello,
>
> Le 23/09/2016 14:04, Atsushi Kumagai a ?crit :
>>> Does someone have an idea of where this could come from ?
>>
>> Thanks for your report, but I'm afraid that I'm going on
>> vacation till Oct 2.
>> I hope someone helps you until I'm back.
>>
>>
>> Regards,
>> Atsushi Kumagai
>>
>
> As a follow up to my question, I've been investigating the issue. The source of
> the problem seems to come from readpage_elf() which tries to read to an
> inexistant page :
>
> readpage_elf: Attempt to read non-existent page at 0x1a7b7fff5000.
>
> The error happens when readpage_elf() is called from section_mem_map_addr with
> pgaddr, which is derived from paddr. This one comes from :
>
>    paddr = vaddr_to_paddr(addr)
>
> When tracing vaddr_to_paddr, I see a difference in the calculation. on a 4.4
> kernel :
>
>   info->phys_base = 0
>
> On 4.8 :
>   info->phys_base = 0xffffffffe3800000
>
> So the paddr values used to define pgaddr are :
>
> for 4.4 kernels : 0x3fff4000
> for 4.8 kernels : 0x1a7b7fff5000
>
> Running makedumpfile --dump-dmesg in debug mode leads to :
>
> 4.4 kernel :
>
> sadump: does not have partition header
> sadump: read dump device as unknown format
> sadump: unknown format
> LOAD (0)
>   phys_start : 1000000
>   phys_end   : 2224000
>   virt_start : ffffffff81000000
>   virt_end   : ffffffff82224000
> LOAD (1)
>   phys_start : 1000
>   phys_end   : 9fc00
>   virt_start : ffff880000001000
>   virt_end   : ffff88000009fc00
> LOAD (2)
>   phys_start : 100000
>   phys_end   : 2b000000
>   virt_start : ffff880000100000
>   virt_end   : ffff88002b000000
> LOAD (3)
>   phys_start : 33000000
>   phys_end   : 3fffe000
>   virt_start : ffff880033000000
>   virt_end   : ffff88003fffe000
> Linux kdump
> page_size    : 4096
>
> max_mapnr    : 3fffe
>
> Buffer size for the cyclic mode: 65535
>
> num of NODEs : 1
>
>
> Memory type  : SPARSEMEM_EX
>
> mem_map (0)
>   mem_map    : ffffea0000000000
>   pfn_start  : 0
>   pfn_end    : 8000
> mem_map (1)
>   mem_map    : ffffea0000200000
>   pfn_start  : 8000
>   pfn_end    : 10000
> mem_map (2)
>   mem_map    : ffffea0000400000
>   pfn_start  : 10000
>   pfn_end    : 18000
> mem_map (3)
>   mem_map    : ffffea0000600000
>   pfn_start  : 18000
>   pfn_end    : 20000
> mem_map (4)
>   mem_map    : ffffea0000800000
>   pfn_start  : 20000
>   pfn_end    : 28000
> mem_map (5)
>   mem_map    : ffffea0000a00000
>   pfn_start  : 28000
>   pfn_end    : 30000
> mem_map (6)
>   mem_map    : ffffea0000c00000
>   pfn_start  : 30000
>   pfn_end    : 38000
> mem_map (7)
>   mem_map    : ffffea0000e00000
>   pfn_start  : 38000
>   pfn_end    : 3fffe
> mmap() is available on the kernel.
>
> log_buf       : ffffffff8210521c
> log_end       : 0
> log_buf_len   : 262144
> log_first_idx : 0
> log_next_idx  : 141176
>
> The dmesg log is saved to /tmp/titi.
>
> makedumpfile Completed.
>
>
> For 4.8 kernels :
> sadump: does not have partition header
> sadump: read dump device as unknown format
> sadump: unknown format
> LOAD (0)
>   phys_start : 7200000
>   phys_end   : 847d000
>   virt_start : ffffffffa3a00000
>   virt_end   : ffffffffa4c7d000
> LOAD (1)
>   phys_start : 1000
>   phys_end   : 9fc00
>   virt_start : ffff880000001000
>   virt_end   : ffff88000009fc00
> LOAD (2)
>   phys_start : 100000
>   phys_end   : 2b000000
>   virt_start : ffff880000100000
>   virt_end   : ffff88002b000000
> LOAD (3)
>   phys_start : 33000000
>   phys_end   : 3fffe000
>   virt_start : ffff880033000000
>   virt_end   : ffff88003fffe000
> Linux kdump
> page_size    : 4096
>
> max_mapnr    : 3fffe
>
> Buffer size for the cyclic mode: 65535
> The kernel version is not supported.
> The makedumpfile operation may be incomplete.
>
> num of NODEs : 1
>
>
> Memory type  : SPARSEMEM_EX
>
> mem_map (0)
>   mem_map    : 0
>   pfn_start  : 0
>   pfn_end    : 8000
> mem_map (1)
>   mem_map    : 0
>   pfn_start  : 8000
>   pfn_end    : 10000
> mem_map (2)
>   mem_map    : 0
>   pfn_start  : 10000
>   pfn_end    : 18000
> mem_map (3)
>   mem_map    : 0
>   pfn_start  : 18000
>   pfn_end    : 20000
> mem_map (4)
>   mem_map    : 0
>   pfn_start  : 20000
>   pfn_end    : 28000
> mem_map (5)
>   mem_map    : 0
>   pfn_start  : 28000
>   pfn_end    : 30000
> mem_map (6)
>   mem_map    : 0
>   pfn_start  : 30000
>   pfn_end    : 38000
> mem_map (7)
>   mem_map    : 0
>   pfn_start  : 38000
>   pfn_end    : 3fffe
> mmap() is available on the kernel.
>
> log_buf       : ffffffffa4b3c19c
> log_end       : 0
> log_buf_len   : 262144
> log_first_idx : 0
> log_next_idx  : 43160
>
> The dmesg log is saved to /tmp/toto.
>
> makedumpfile Completed.
>
>
> I don't know if it is to be expected with kernels 4.8 to have all mem_map
> addresses set to 0, unlike with k4.4 :
>
> mem_map (0)
> mem_map : 0
> pfn_start : 0
> pfn_end : 8000
>
> Any comment appreciated while I continue to investigate.
>
> Kind regards,
>
> ...Louis
>

I have now completed the kernel bisection between 4.7.8 and 4.8-rc1 and
identified the kernel modification that triggers the errors cited above :

> commit 021182e52fe01c1f7b126f97fd6ba048dc4234fd
> Author: Thomas Garnier <thgarnie at google.com>
> Date:   Tue Jun 21 17:47:03 2016 -0700
>
>     x86/mm: Enable KASLR for physical mapping memory regions
>
>     Add the physical mapping in the list of randomized memory regions.
>
>     The physical memory mapping holds most allocations from boot and heap
>     allocators. Knowing the base address and physical memory size, an attacker
>     can deduce the PDE virtual address for the vDSO memory page. This attack
>     was demonstrated at CanSecWest 2016, in the following presentation:
>
>       "Getting Physical: Extreme Abuse of Intel Based Paged Systems":
>       https://github.com/n3k/CansecWest2016_Getting_Physical_Extreme_Abuse_of_Intel_Based_Paging_Systems/blob/master/Presentation/CanSec2016_Presentation.pdf
>
>     (See second part of the presentation).
>
>     The exploits used against Linux worked successfully against 4.6+ but
>     fail with KASLR memory enabled:
>
>       https://github.com/n3k/CansecWest2016_Getting_Physical_Extreme_Abuse_of_Intel_Based_Paging_Systems/tree/master/Demos/Linux/exploits
>
>     Similar research was done at Google leading to this patch proposal.
>
>     Variants exists to overwrite /proc or /sys objects ACLs leading to
>     elevation of privileges. These variants were tested against 4.6+.
>
>     The page offset used by the compressed kernel retains the static value
>     since it is not yet randomized during this boot stage.
>
>     Signed-off-by: Thomas Garnier <thgarnie at google.com>
>     Signed-off-by: Kees Cook <keescook at chromium.org>
>     Cc: Alexander Kuleshov <kuleshovmail at gmail.com>
<truncated>

The interesting change seems to be :

> -#define __PAGE_OFFSET           _AC(0xffff880000000000, UL)
> +#define __PAGE_OFFSET_BASE      _AC(0xffff880000000000, UL)
> +#ifdef CONFIG_RANDOMIZE_MEMORY
> +#define __PAGE_OFFSET           page_offset_base
> +#else
> +#define __PAGE_OFFSET           __PAGE_OFFSET_BASE
> +#endif /* CONFIG_RANDOMIZE_MEMORY */

I'll try to see if I can fix that.

Kind regards,

...Louis




-- 
Louis Bouchard
Software engineer, Cloud & Sustaining eng.
Canonical Ltd
Ubuntu developer                       Debian Maintainer
GPG : 429D 7A3B DD05 B6F8 AF63  B9C4 8B3D 867C 823E 7A61


From panand at redhat.com  Mon Oct 24 09:48:41 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 24 Oct 2016 22:18:41 +0530
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized base
 enabled
Message-ID: <cover.1477327674.git.panand@redhat.com>

Patch 1/4 fixes page_offset calculation, so that it is correctly calculated
on KASLR enabled kernel as well.
Patch 2/4 simplifies VA to PA translation. New code has been benchmarked
against old code on a 4T system.
Patch 3/4 and 4/4 is removal of (now) unnecessary code.

I think, we should find a way to kill find_vememmap() as well, so that
VMEMMAP_START can be removed. I have very limited idea about x86, so unable
to do that as of now.

Pratyush Anand (4):
  x86_64: Calculate page_offset from pt_load
  x86_64: translate all VA to PA using page table values
  x86_64: kill is_vmalloc_addr_x86_64()
  x86_64: kill some unused initialization

 arch/x86_64.c  | 84 ++++++++++++++++++++--------------------------------------
 makedumpfile.h |  9 +++----
 2 files changed, 32 insertions(+), 61 deletions(-)

-- 
2.7.4



From panand at redhat.com  Mon Oct 24 09:48:42 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 24 Oct 2016 22:18:42 +0530
Subject: [PATCH] temp
In-Reply-To: <cover.1477327674.git.panand@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
Message-ID: <49c4e7da099ef77d419d540d0e56618c67926928.1476955959.git.panand@redhat.com>

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/x86_64.c  | 10 ++++++++--
 makedumpfile.h |  4 ++--
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/arch/x86_64.c b/arch/x86_64.c
index ddf7be6bc57b..3a53b4fa03ed 100644
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -187,6 +187,12 @@ vtop4_x86_64(unsigned long vaddr)
 {
 	unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
 	unsigned long pte_paddr, pte;
+	unsigned long phys_base;
+
+	if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
+		phys_base = info->phys_base;
+	else
+		phys_base = 0;
 
 	if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
 		ERRMSG("Can't get the symbol of init_level4_pgt.\n");
@@ -196,9 +202,9 @@ vtop4_x86_64(unsigned long vaddr)
 	/*
 	 * Get PGD.
 	 */
-	page_dir  = SYMBOL(init_level4_pgt);
+	page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + phys_base;
 	page_dir += pml4_index(vaddr) * sizeof(unsigned long);
-	if (!readmem(VADDR, page_dir, &pml4, sizeof pml4)) {
+	if (!readmem(PADDR, page_dir, &pml4, sizeof pml4)) {
 		ERRMSG("Can't get pml4 (page_dir:%lx).\n", page_dir);
 		return NOT_PADDR;
 	}
diff --git a/makedumpfile.h b/makedumpfile.h
index f0154226bcb8..f64652e34901 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -876,12 +876,12 @@ int is_vmalloc_addr_x86_64(ulong vaddr);
 int get_phys_base_x86_64(void);
 int get_machdep_info_x86_64(void);
 int get_versiondep_info_x86_64(void);
-unsigned long long vaddr_to_paddr_x86_64(unsigned long vaddr);
+unsigned long long vtop4_x86_64(unsigned long vaddr);
 #define find_vmemmap()		find_vmemmap_x86_64()
 #define get_phys_base()		get_phys_base_x86_64()
 #define get_machdep_info()	get_machdep_info_x86_64()
 #define get_versiondep_info()	get_versiondep_info_x86_64()
-#define vaddr_to_paddr(X)	vaddr_to_paddr_x86_64(X)
+#define vaddr_to_paddr(X)	vtop4_x86_64(X)
 #define is_phys_addr(X)		(!is_vmalloc_addr_x86_64(X))
 #endif /* x86_64 */
 
-- 
2.7.4



From panand at redhat.com  Mon Oct 24 09:48:45 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 24 Oct 2016 22:18:45 +0530
Subject: [PATCH Makedumpfile 3/4] x86_64: kill is_vmalloc_addr_x86_64()
In-Reply-To: <cover.1477327674.git.panand@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
Message-ID: <81ec62b304f3a1e28e128e19d2744ffed2e4cf65.1477327674.git.panand@redhat.com>

>From kernel documentation:
ffffffff80000000 - ffffffff9fffffff (=512 MB)  kernel text mapping, from phys 0
ffffffffa0000000 - ffffffffff5fffff (=1526 MB) module mapping space

So, it is only the module area which is lying above __START_KERNEL_map.
However, kexec-tools only creates PT_LOAD segments for kernel text region
and crash memory region. So, we can safely remove the check for
!is_vmalloc_addr_x86_64() from get_phys_base_x86_64().

Since, this was the last usage of is_vmalloc_addr_x86_64(), so kill it as
well.

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/x86_64.c  | 14 +-------------
 makedumpfile.h |  3 +--
 2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/arch/x86_64.c b/arch/x86_64.c
index fe2764a8bec2..597cdac36dfc 100644
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -21,17 +21,6 @@
 extern struct vmap_pfns *gvmem_pfns;
 extern int nr_gvmem_pfns;
 
-int
-is_vmalloc_addr_x86_64(ulong vaddr)
-{
-	/*
-	 *  vmalloc, virtual memmap, and module space as VMALLOC space.
-	 */
-	return ((vaddr >= VMALLOC_START && vaddr <= VMALLOC_END)
-	    || (vaddr >= VMEMMAP_START && vaddr <= VMEMMAP_END)
-	    || (vaddr >= MODULES_VADDR && vaddr <= MODULES_END));
-}
-
 static unsigned long
 get_xen_p2m_mfn(void)
 {
@@ -75,8 +64,7 @@ get_phys_base_x86_64(void)
 	info->phys_base = 0; /* default/traditional */
 
 	for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
-		if ((virt_start >= __START_KERNEL_map) &&
-		    !(is_vmalloc_addr_x86_64(virt_start))) {
+		if (virt_start >= __START_KERNEL_map) {
 
 			info->phys_base = phys_start -
 			    (virt_start & ~(__START_KERNEL_map));
diff --git a/makedumpfile.h b/makedumpfile.h
index 13559651feb6..8a96da1f61bd 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -859,7 +859,6 @@ unsigned long long vaddr_to_paddr_x86(unsigned long vaddr);
 #endif /* x86 */
 
 #ifdef __x86_64__
-int is_vmalloc_addr_x86_64(ulong vaddr);
 int get_phys_base_x86_64(void);
 int get_machdep_info_x86_64(void);
 int get_versiondep_info_x86_64(void);
@@ -869,7 +868,7 @@ unsigned long long vtop4_x86_64(unsigned long vaddr);
 #define get_machdep_info()	get_machdep_info_x86_64()
 #define get_versiondep_info()	get_versiondep_info_x86_64()
 #define vaddr_to_paddr(X)	vtop4_x86_64(X)
-#define is_phys_addr(X)		(!is_vmalloc_addr_x86_64(X))
+#define is_phys_addr(X)		stub_true_ul(X)
 #endif /* x86_64 */
 
 #ifdef __powerpc64__ /* powerpc64 */
-- 
2.7.4



From panand at redhat.com  Mon Oct 24 09:48:43 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 24 Oct 2016 22:18:43 +0530
Subject: [PATCH Makedumpfile 1/4] x86_64: Calculate page_offset from pt_load
In-Reply-To: <cover.1477327674.git.panand@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
Message-ID: <4b2497eff40bd47eef59cdd6af165e700cfd4408.1477327674.git.panand@redhat.com>

page_offset can always be calculated as 'virtual - physical' for a direct
mapping area on x86. Therefore, remove the version dependent calculation
and use this method.

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

diff --git a/arch/x86_64.c b/arch/x86_64.c
index ddf7be6bc57b..a96fd8ae00a1 100644
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -44,6 +44,24 @@ get_xen_p2m_mfn(void)
 	return NOT_FOUND_LONG_VALUE;
 }
 
+static int
+get_page_offset_x86_64(void)
+{
+	int i;
+	unsigned long long phys_start;
+	unsigned long long virt_start;
+
+	for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
+		if (virt_start >= __START_KERNEL_map) {
+			info->page_offset = virt_start - phys_start;
+			return TRUE;
+		}
+	}
+
+	ERRMSG("Can't get any pt_load to calculate page offset.\n");
+	return FALSE;
+}
+
 int
 get_phys_base_x86_64(void)
 {
@@ -159,10 +177,8 @@ get_versiondep_info_x86_64(void)
 	else
 		info->max_physmem_bits  = _MAX_PHYSMEM_BITS_2_6_31;
 
-	if (info->kernel_version < KERNEL_VERSION(2, 6, 27))
-		info->page_offset = __PAGE_OFFSET_ORIG;
-	else
-		info->page_offset = __PAGE_OFFSET_2_6_27;
+	if (!get_page_offset_x86_64())
+		return FALSE;
 
 	if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
 		info->vmalloc_start = VMALLOC_START_ORIG;
-- 
2.7.4



From panand at redhat.com  Mon Oct 24 09:48:46 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 24 Oct 2016 22:18:46 +0530
Subject: [PATCH Makedumpfile 4/4] x86_64: kill some unused initialization
In-Reply-To: <cover.1477327674.git.panand@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
Message-ID: <852afb9126c5e52deff47ffb195e2a151a7339ed.1477327674.git.panand@redhat.com>

VMALLOC_START, VMALLOC_END, MODULES_VADDR and MODULES_END are mo more
needed for x86_64 now. So, kill their initialization.

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/x86_64.c  | 4 ----
 makedumpfile.h | 2 --
 2 files changed, 6 deletions(-)

diff --git a/arch/x86_64.c b/arch/x86_64.c
index 597cdac36dfc..13990cef839b 100644
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -169,13 +169,9 @@ get_versiondep_info_x86_64(void)
 		return FALSE;
 
 	if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
-		info->vmalloc_start = VMALLOC_START_ORIG;
-		info->vmalloc_end   = VMALLOC_END_ORIG;
 		info->vmemmap_start = VMEMMAP_START_ORIG;
 		info->vmemmap_end   = VMEMMAP_END_ORIG;
 	} else {
-		info->vmalloc_start = VMALLOC_START_2_6_31;
-		info->vmalloc_end   = VMALLOC_END_2_6_31;
 		info->vmemmap_start = VMEMMAP_START_2_6_31;
 		info->vmemmap_end   = VMEMMAP_END_2_6_31;
 	}
diff --git a/makedumpfile.h b/makedumpfile.h
index 8a96da1f61bd..338c651388f0 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -575,8 +575,6 @@ int get_va_bits_arm64(void);
 #define __START_KERNEL_map	(0xffffffff80000000)
 #define KERNEL_IMAGE_SIZE_ORIG		(0x0000000008000000) /* 2.6.25, or former */
 #define KERNEL_IMAGE_SIZE_2_6_26	(0x0000000020000000) /* 2.6.26, or later  */
-#define MODULES_VADDR          (__START_KERNEL_map + NUMBER(KERNEL_IMAGE_SIZE))
-#define MODULES_END		(0xfffffffffff00000)
 #define KVBASE			PAGE_OFFSET
 #define _SECTION_SIZE_BITS	(27)
 #define _MAX_PHYSMEM_BITS_ORIG		(40)
-- 
2.7.4



From panand at redhat.com  Mon Oct 24 09:48:44 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 24 Oct 2016 22:18:44 +0530
Subject: [PATCH Makedumpfile 2/4] x86_64: translate all VA to PA using page
 table values
In-Reply-To: <cover.1477327674.git.panand@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
Message-ID: <b54b1e73bc4302fa7222c44a9cf46d57aa93b8ba.1477327674.git.panand@redhat.com>

Currently we translate some of the VA areas using linear mapping while some
other(which can not be linearly mapped) using page table.

However, we will have entry of a page in the page table irrespective of its
virtual region. So, we can always look into page table for any VA to PA
translation. This approach will solve lot of complexity in makedumpfile. It
will in turn remove dependency over variables like VMALLOC_START,
MODULES_VADDR etc whose definition keeps changing in newer kernel version.

Moreover, I do not see any side effect of this approach in terms of
execution timing. I tested with IBM x3950 X6 machine having 4136359 MB of
memory. These are the results of makedumpfile execution time:

Without this patch:
===================
With -d 31:
Trial 1: 237.59526248 S
Trial 2: 235.236914962 S
Trail 3: 237.678712045 S

With -d 1:
Trial 1: 2548.905296877 S
Trial 2: 2549.759881756 S

With this patch:
===================
With -d 31:
Trial 1: 232.713841516 S
Trial 2: 228.45697177 S
Trail 3: 232.942262441 S

With -d 1:
Trial 1: 2768.424565806 S
Trial 2: 2749.622115455 S
Trail 3: 2537.770359073 S

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/x86_64.c  | 42 ++++++++----------------------------------
 makedumpfile.h |  4 ++--
 2 files changed, 10 insertions(+), 36 deletions(-)

diff --git a/arch/x86_64.c b/arch/x86_64.c
index a96fd8ae00a1..fe2764a8bec2 100644
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -203,6 +203,12 @@ vtop4_x86_64(unsigned long vaddr)
 {
 	unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
 	unsigned long pte_paddr, pte;
+	unsigned long phys_base;
+
+	if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
+		phys_base = info->phys_base;
+	else
+		phys_base = 0;
 
 	if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
 		ERRMSG("Can't get the symbol of init_level4_pgt.\n");
@@ -212,9 +218,9 @@ vtop4_x86_64(unsigned long vaddr)
 	/*
 	 * Get PGD.
 	 */
-	page_dir  = SYMBOL(init_level4_pgt);
+	page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + phys_base;
 	page_dir += pml4_index(vaddr) * sizeof(unsigned long);
-	if (!readmem(VADDR, page_dir, &pml4, sizeof pml4)) {
+	if (!readmem(PADDR, page_dir, &pml4, sizeof pml4)) {
 		ERRMSG("Can't get pml4 (page_dir:%lx).\n", page_dir);
 		return NOT_PADDR;
 	}
@@ -285,38 +291,6 @@ vtop4_x86_64(unsigned long vaddr)
 	return (pte & ENTRY_MASK) + PAGEOFFSET(vaddr);
 }
 
-unsigned long long
-vaddr_to_paddr_x86_64(unsigned long vaddr)
-{
-	unsigned long phys_base;
-	unsigned long long paddr;
-
-	/*
-	 * Check the relocatable kernel.
-	 */
-	if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
-		phys_base = info->phys_base;
-	else
-		phys_base = 0;
-
-	if (is_vmalloc_addr_x86_64(vaddr)) {
-		if ((paddr = vtop4_x86_64(vaddr)) == NOT_PADDR) {
-			ERRMSG("Can't convert a virtual address(%lx) to " \
-			    "physical address.\n", vaddr);
-			return NOT_PADDR;
-		}
-	} else if (vaddr >= __START_KERNEL_map) {
-		paddr = vaddr - __START_KERNEL_map + phys_base;
-
-	} else {
-		if (is_xen_memory())
-			paddr = vaddr - PAGE_OFFSET_XEN_DOM0;
-		else
-			paddr = vaddr - PAGE_OFFSET;
-	}
-	return paddr;
-}
-
 /*
  * for Xen extraction
  */
diff --git a/makedumpfile.h b/makedumpfile.h
index a5955ff750e5..13559651feb6 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -863,12 +863,12 @@ int is_vmalloc_addr_x86_64(ulong vaddr);
 int get_phys_base_x86_64(void);
 int get_machdep_info_x86_64(void);
 int get_versiondep_info_x86_64(void);
-unsigned long long vaddr_to_paddr_x86_64(unsigned long vaddr);
+unsigned long long vtop4_x86_64(unsigned long vaddr);
 #define find_vmemmap()		find_vmemmap_x86_64()
 #define get_phys_base()		get_phys_base_x86_64()
 #define get_machdep_info()	get_machdep_info_x86_64()
 #define get_versiondep_info()	get_versiondep_info_x86_64()
-#define vaddr_to_paddr(X)	vaddr_to_paddr_x86_64(X)
+#define vaddr_to_paddr(X)	vtop4_x86_64(X)
 #define is_phys_addr(X)		(!is_vmalloc_addr_x86_64(X))
 #endif /* x86_64 */
 
-- 
2.7.4



From panand at redhat.com  Mon Oct 24 09:51:07 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 24 Oct 2016 22:21:07 +0530
Subject: [PATCH] temp
In-Reply-To: <49c4e7da099ef77d419d540d0e56618c67926928.1476955959.git.panand@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <49c4e7da099ef77d419d540d0e56618c67926928.1476955959.git.panand@redhat.com>
Message-ID: <CAHB_GuofYgSLpTJap38xn3eACrb9SfLL_Z9k6OgYnrq+c7tanA@mail.gmail.com>

Ohhh..Please ignore this patch. This temporary changes were lying in
my directory and went away.

Sorry for this noise.

~Pratyush

On Mon, Oct 24, 2016 at 10:18 PM, Pratyush Anand <panand at redhat.com> wrote:
> Signed-off-by: Pratyush Anand <panand at redhat.com>
> ---
>  arch/x86_64.c  | 10 ++++++++--
>  makedumpfile.h |  4 ++--
>  2 files changed, 10 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86_64.c b/arch/x86_64.c
> index ddf7be6bc57b..3a53b4fa03ed 100644
> --- a/arch/x86_64.c
> +++ b/arch/x86_64.c
> @@ -187,6 +187,12 @@ vtop4_x86_64(unsigned long vaddr)
>  {
>         unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
>         unsigned long pte_paddr, pte;
> +       unsigned long phys_base;
> +
> +       if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
> +               phys_base = info->phys_base;
> +       else
> +               phys_base = 0;
>
>         if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
>                 ERRMSG("Can't get the symbol of init_level4_pgt.\n");
> @@ -196,9 +202,9 @@ vtop4_x86_64(unsigned long vaddr)
>         /*
>          * Get PGD.
>          */
> -       page_dir  = SYMBOL(init_level4_pgt);
> +       page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + phys_base;
>         page_dir += pml4_index(vaddr) * sizeof(unsigned long);
> -       if (!readmem(VADDR, page_dir, &pml4, sizeof pml4)) {
> +       if (!readmem(PADDR, page_dir, &pml4, sizeof pml4)) {
>                 ERRMSG("Can't get pml4 (page_dir:%lx).\n", page_dir);
>                 return NOT_PADDR;
>         }
> diff --git a/makedumpfile.h b/makedumpfile.h
> index f0154226bcb8..f64652e34901 100644
> --- a/makedumpfile.h
> +++ b/makedumpfile.h
> @@ -876,12 +876,12 @@ int is_vmalloc_addr_x86_64(ulong vaddr);
>  int get_phys_base_x86_64(void);
>  int get_machdep_info_x86_64(void);
>  int get_versiondep_info_x86_64(void);
> -unsigned long long vaddr_to_paddr_x86_64(unsigned long vaddr);
> +unsigned long long vtop4_x86_64(unsigned long vaddr);
>  #define find_vmemmap()         find_vmemmap_x86_64()
>  #define get_phys_base()                get_phys_base_x86_64()
>  #define get_machdep_info()     get_machdep_info_x86_64()
>  #define get_versiondep_info()  get_versiondep_info_x86_64()
> -#define vaddr_to_paddr(X)      vaddr_to_paddr_x86_64(X)
> +#define vaddr_to_paddr(X)      vtop4_x86_64(X)
>  #define is_phys_addr(X)                (!is_vmalloc_addr_x86_64(X))
>  #endif /* x86_64 */
>
> --
> 2.7.4
>


From sgoel at codeaurora.org  Mon Oct 24 15:53:47 2016
From: sgoel at codeaurora.org (Goel, Sameer)
Date: Mon, 24 Oct 2016 16:53:47 -0600
Subject: kexec and arm64 advice
In-Reply-To: <CAKYm0coteEEapCNwmj+KmGd57C_C3--nXQfjyD_FLoGXSkqMkQ@mail.gmail.com>
References: <CAKYm0coteEEapCNwmj+KmGd57C_C3--nXQfjyD_FLoGXSkqMkQ@mail.gmail.com>
Message-ID: <16c384ed-0875-daa8-b52a-f03af764460b@codeaurora.org>

It seems that the kexec_load syscall is not defined. Can you please 
check the configs of your running kernel once again?

Thanks,
Sameer

On 10/24/2016 8:42 AM, Simon T wrote:
> Hi,
>
> I'm trying to get kexec working on a cross-compiled arm64/aarch64
> system, using Linux kernel 4.4.23. I'm using kexec-tool's master
> branch (commit e345e27417db00a9e754ca0ca14b2ec87d0552f7 from
> https://git.kernel.org/cgit/linux/kernel/git/geoff/kexec-tools.git). I
> initially tried using the patches for linux-kexec's kexec-13 branch
> with manual massaging in some spots because kexec-13 is for 4.4.0 not
> 4.4.23. Both tools and kernel appear to build fine, however when it
> comes time to kexec, I encounter this message: "kexec_load failed:
> Function not implemented"
>
> Searching through the patches, I don't find any reference to kexec_load itself.
>
> Should I be applying a different version of kexec-tools, or
> linux-kexec patches, to my build? (I'm restricted to 4.4.23 as the
> base kernel)
>
> Is there a way post compile to check if the kexec_load function is
> implemented, aside from actually deploying the image and calling
> kexec? I've run strings against the Image but it doesn't give an exact
> match for kexec_load (see below).
>
> Anything else I should be looking at?
>
> # kexec -l /mnt/target/boot/vmlinux --initrd=/tmp/root.sfs
> Modified cmdline:root=/dev/mmcblk0p2
> Unable to find /proc/device-tree/chosen/[linux,]stdout-path, printing
> from purgatory is disabled
> kexec_load failed: Function not implemented
> entry       = 0x8095f000 flags = 0xb70000
> nr_segments = 4
> segment[0].buf   = 0x7fa0f64010
> segment[0].bufsz = 0x7fbc00
> segment[0].mem   = 0x80080000
> segment[0].memsz = 0x8d0000
> segment[1].buf   = 0x20cc0830
> segment[1].bufsz = 0xe515
> segment[1].mem   = 0x80950000
> segment[1].memsz = 0xf000
> segment[2].buf   = 0x20ccf840
> segment[2].bufsz = 0x6080
> segment[2].mem   = 0x8095f000
> segment[2].memsz = 0x7000
> segment[3].buf   = 0x7f9e843010
> segment[3].bufsz = 0x2720000
> segment[3].mem   = 0xc0000000
> segment[3].memsz = 0x2720000
>
> (I've also tried kexec -l with boot/Image instead of boot/vmlinux)
>
> $ grep -i kexec .config
> CONFIG_KERNEL_KEXEC=y
> CONFIG_PACKAGE_kexec-tools=y
> CONFIG_KEXEC_TOOLS_TARGET_NAME="aarch64"
> # CONFIG_KEXEC_TOOLS_kdump is not set
> CONFIG_KEXEC_ZLIB=y
> # CONFIG_KEXEC_LZMA is not set
>
> $ strings <build_dir>/arch/arm64/boot/Image  | grep kexec_load
> Wcompat_sys_kexec_load
> Wsys_kexec_load
>
> Thanks!
>
> Simon
>
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
>

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.


From sgoel at codeaurora.org  Mon Oct 24 16:02:11 2016
From: sgoel at codeaurora.org (Goel, Sameer)
Date: Mon, 24 Oct 2016 17:02:11 -0600
Subject: [PATCH v3 1/8] arm64: identify PHYS_OFFSET correctly
In-Reply-To: <20160928074806.GA5232@localhost>
References: <20160907043401.6403-1-takahiro.akashi@linaro.org>
 <20160907043401.6403-2-takahiro.akashi@linaro.org>
 <CAHB_GuqcaGxj48RNW_72Q6tMgoat7oRG0LKg0S7mJs8=_Ft8Lw@mail.gmail.com>
 <20160928074806.GA5232@localhost>
Message-ID: <bae581c9-9a2b-6cca-75c4-3a5f8c215898@codeaurora.org>

We should look for the kernel code and get the physical offset by 
rounding the address down to 2M. For ARM systems if memory is not 
considered system ram then it is considered device memory. Even if a 
region is not reserved the memory blocks would be sorted.

In cases where the kernel code is not starting at offset 0, the kexec 
command will not load the kernel at the same start address as the 
running kernel. This brakes an implicit kexec assumption.

Thanks,
Sameer

On 9/28/2016 1:48 AM, AKASHI Takahiro wrote:
> On Tue, Sep 27, 2016 at 09:19:51PM +0530, Pratyush Anand wrote:
>> On Wed, Sep 7, 2016 at 10:03 AM, AKASHI Takahiro
>> <takahiro.akashi at linaro.org> wrote:
>>> Due to the kernel patch[1], the current code will not be able to identify
>>
>> [1] is mentioned in cover letter only, not here.
>
> Oops, thanks.
>
>>> the correct value of PHYS_OFFSET if some "reserved" memory region, which
>>> is likely to be UEFI runtime services code/data, exists at an address below
>>> the first "System RAM" regions.
>>>
>>> This patch fixes this issue.
>>>
>>> Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
>>> ---
>>>  kexec/arch/arm64/iomem.h       |  7 +++++++
>>>  kexec/arch/arm64/kexec-arm64.c | 22 +++++++++++++++++-----
>>>  2 files changed, 24 insertions(+), 5 deletions(-)
>>>  create mode 100644 kexec/arch/arm64/iomem.h
>>>
>>> diff --git a/kexec/arch/arm64/iomem.h b/kexec/arch/arm64/iomem.h
>>> new file mode 100644
>>> index 0000000..7fd66eb
>>> --- /dev/null
>>> +++ b/kexec/arch/arm64/iomem.h
>>> @@ -0,0 +1,7 @@
>>> +#ifndef IOMEM_H
>>> +#define IOMEM_H
>>> +
>>> +#define SYSTEM_RAM             "System RAM\n"
>>> +#define IOMEM_RESERVED         "reserved\n"
>>> +
>>> +#endif
>>> diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
>>> index 7183dac..bc96c76 100644
>>> --- a/kexec/arch/arm64/kexec-arm64.c
>>> +++ b/kexec/arch/arm64/kexec-arm64.c
>>> @@ -21,6 +21,7 @@
>>>  #include "crashdump-arm64.h"
>>>  #include "dt-ops.h"
>>>  #include "fs2dt.h"
>>> +#include "iomem.h"
>>>  #include "kexec-syscall.h"
>>>  #include "arch/options.h"
>>>
>>> @@ -465,18 +466,28 @@ void add_segment(struct kexec_info *info, const void *buf, size_t bufsz,
>>>   * get_memory_ranges_iomem_cb - Helper for get_memory_ranges_iomem.
>>>   */
>>>
>>> +static int count_memory_ranges;
>>
>> IMHO improving definition of kexec_iomem_for_each_line() and
>> callback() for handling NULL match case would have been a better
>> choice than introducing a new static variable. callback() can return
>> -ve in case of error, 0 in case of no match and 1 in case of (one)
>> match.
>
> Maybe. But we have to be careful not to change other arch's results.
> Or follow arm's approach.
>
> -Takahiro AKASHI
>
>> ~Pratyush
>>
>>> +
>>>  static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
>>>         unsigned long long base, unsigned long long length)
>>>  {
>>>         struct memory_range *r;
>>>
>>> -       if (nr >= KEXEC_SEGMENT_MAX)
>>> +       if (count_memory_ranges >= KEXEC_SEGMENT_MAX)
>>>                 return -1;
>>>
>>> -       r = (struct memory_range *)data + nr;
>>> -       r->type = RANGE_RAM;
>>> +       r = (struct memory_range *)data + count_memory_ranges;
>>> +
>>> +       if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)))
>>> +               r->type = RANGE_RAM;
>>> +       else if (!strncmp(str, IOMEM_RESERVED, strlen(IOMEM_RESERVED)))
>>> +               r->type = RANGE_RESERVED;
>>> +       else
>>> +               return 0;
>>> +
>>>         r->start = base;
>>>         r->end = base + length - 1;
>>> +       count_memory_ranges++;
>>>
>>>         set_phys_offset(r->start);
>>>
>>> @@ -493,9 +504,10 @@ static int get_memory_ranges_iomem_cb(void *data, int nr, char *str,
>>>  static int get_memory_ranges_iomem(struct memory_range *array,
>>>         unsigned int *count)
>>>  {
>>> -       *count = kexec_iomem_for_each_line("System RAM\n",
>>> -               get_memory_ranges_iomem_cb, array);
>>> +       count_memory_ranges = 0;
>>> +       kexec_iomem_for_each_line(NULL, get_memory_ranges_iomem_cb, array);
>>>
>>> +       *count = count_memory_ranges;
>>>         if (!*count) {
>>>                 dbgprintf("%s: failed: No RAM found.\n", __func__);
>>>                 return -EFAILED;
>>> --
>>> 2.9.0
>>>
>
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
>

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.


From panand at redhat.com  Tue Oct 25 00:22:52 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 12:52:52 +0530
Subject: [PATCH Makedumpfile 00/10] arm64 cleanup and kaslr support
Message-ID: <cover.1477378297.git.panand@redhat.com>

These patches were lying in my tree for quite some time now. VMCOREINFO
numbers/symbols used in these patches have been made part of kdump kernel
patches for last few versions including v26. So, there seems no contention
on embedding VA_BITS, kimage_voffset and PHYS_OFFSET into vmcore.

These patches cleans up a lot arm64 code and also immunize it with many
kernel changes. Additionally,it adds 4 level 4K page support and support for
KASLR enabled kernel.

Azriel Samson (1):
  arm64: Add support for 4level 4K page translations table

Pratyush Anand (9):
  arm64: cleanup code, comment, blank space, blank lines etc
  read_vmcoreinfo_long: Allow to read hex values as well
  Introduce read_vmcoreinfo_ulong()
  arm64: use already available PAGESIZE() and PAGESHIFT() macros
  arm64: fix page_offset definition
  arm64: fix re-filtering
  arm64: use value of VA_BITS and PHYS_OFFSET embedded into vmcore
  arm64: immunize identity mapped address finding w.r.t. kernel changes
  arm64: fix memory layout as per changes in v4.6 kernel

 arch/arm64.c   | 245 ++++++++++++++++++++++-----------------------------------
 makedumpfile.c |  46 +++++++++++
 makedumpfile.h |  28 +++++--
 3 files changed, 162 insertions(+), 157 deletions(-)

-- 
2.7.4



From panand at redhat.com  Tue Oct 25 00:22:53 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 12:52:53 +0530
Subject: [PATCH Makedumpfile 01/10] arm64: cleanup code, comment, blank space,
 blank lines etc
In-Reply-To: <cover.1477378297.git.panand@redhat.com>
References: <cover.1477378297.git.panand@redhat.com>
Message-ID: <38dfdb53501a3cb129444abb190d2a78257139de.1477378297.git.panand@redhat.com>

Do some code cleanup for blank spaces and lines, static function and
commenting style.
Also, re-organize some #defines to place them in a particular fashion.
Remove, redundant #defines.

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/arm64.c | 29 ++++++++++-------------------
 1 file changed, 10 insertions(+), 19 deletions(-)

diff --git a/arch/arm64.c b/arch/arm64.c
index f7540262a6ae..4a2a9a9ec45d 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -35,25 +35,21 @@ typedef struct {
 	pud_t pud;
 } pmd_t;
 
-#define pud_offset(pgd, vaddr) 	((pud_t *)pgd)
+typedef struct {
+	unsigned long pte;
+} pte_t;
 
 #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)
-
-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 PUD_SHIFT		PGDIR_SHIFT
+#define PUD_SIZE		(1UL << PUD_SHIFT)
 #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)
@@ -62,17 +58,14 @@ typedef struct {
 
 #define PAGE_PRESENT		(1 << 0)
 #define SECTIONS_SIZE_BITS	30
-/*
-
-* Highest possible physical address supported.
-*/
+/* Highest possible physical address supported */
 #define PHYS_MASK_SHIFT		48
 #define PHYS_MASK		((1UL << PHYS_MASK_SHIFT) - 1)
 /*
  * Remove the highest order bits that are not a part of the
  * physical address in a section
  */
-#define PMD_SECTION_MASK        ((1UL << 40) - 1)
+#define PMD_SECTION_MASK	((1UL << 40) - 1)
 
 #define PMD_TYPE_MASK		3
 #define PMD_TYPE_SECT		1
@@ -84,15 +77,13 @@ typedef struct {
 #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 pte_index(vaddr) 		(((vaddr) >> 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))
 
-
-#define pmd_offset_pgtbl_lvl_2(pud, vaddr) ((pmd_t *)pud)
-
 #define pmd_index(vaddr)		(((vaddr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
 #define pud_page_vaddr(pud)		(__va(pud_val(pud) & PHYS_MASK & (int32_t)PAGE_MASK))
+#define pmd_offset_pgtbl_lvl_2(pud, vaddr) ((pmd_t *)pud)
 #define pmd_offset_pgtbl_lvl_3(pud, vaddr) ((pmd_t *)pud_page_vaddr((*pud)) + pmd_index(vaddr))
 
 /* kernel struct page size can be kernel version dependent, currently
@@ -128,7 +119,7 @@ get_page_shift_arm64(void)
 	return page_shift;
 }
 
-pmd_t *
+static pmd_t *
 pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
 {
 	if (pgtable_level == 2) {
-- 
2.7.4



From panand at redhat.com  Tue Oct 25 00:22:54 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 12:52:54 +0530
Subject: [PATCH Makedumpfile 02/10] read_vmcoreinfo_long: Allow to read hex
 values as well
In-Reply-To: <cover.1477378297.git.panand@redhat.com>
References: <cover.1477378297.git.panand@redhat.com>
Message-ID: <14ce46e3c2e872543de02b369362864812f3bc39.1477378297.git.panand@redhat.com>

Kernel can also write a hex value in NUMBER(X) string, for example:
vmcoreinfo_append_str("NUMBER(PHYS_OFFSET)=0x%llx\n",PHYS_OFFSET);

Therefore, allow read_vmcoreinfo_long() to read 'base 16' values if, 'base
10' read resulted in a read of invalid character.

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

diff --git a/makedumpfile.c b/makedumpfile.c
index ab9719bb678e..b2ea3ebdd4cb 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -2433,6 +2433,8 @@ read_vmcoreinfo_long(char *str_structure)
 			buf[i - 1] = '\0';
 		if (strncmp(buf, str_structure, strlen(str_structure)) == 0) {
 			data = strtol(buf + strlen(str_structure), &endp, 10);
+			if (strlen(endp) != 0)
+				data = strtol(buf + strlen(str_structure), &endp, 16);
 			if ((data == LONG_MAX) || strlen(endp) != 0) {
 				ERRMSG("Invalid data in %s: %s",
 				    info->name_vmcoreinfo, buf);
-- 
2.7.4



From panand at redhat.com  Tue Oct 25 00:22:55 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 12:52:55 +0530
Subject: [PATCH Makedumpfile 03/10] Introduce read_vmcoreinfo_ulong()
In-Reply-To: <cover.1477378297.git.panand@redhat.com>
References: <cover.1477378297.git.panand@redhat.com>
Message-ID: <34a970eeae39e86d768fba3e0497aa2c0db16f9b.1477378297.git.panand@redhat.com>

Kernel may pass an unsigned number into vmcore. For example ARM64 passes:

vmcoreinfo_append_str("NUMBER(PHYS_OFFSET)=0x%llx\n", PHYS_OFFSET);

Therefore, introducing read_vmcoreinfo_ulong() to read such values
correctly.

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 makedumpfile.c | 34 ++++++++++++++++++++++++++++++++++
 makedumpfile.h | 16 ++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/makedumpfile.c b/makedumpfile.c
index b2ea3ebdd4cb..e248db876858 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -2412,6 +2412,40 @@ read_vmcoreinfo_symbol(char *str_symbol)
 	return symbol;
 }
 
+unsigned long
+read_vmcoreinfo_ulong(char *str_structure)
+{
+	long data = NOT_FOUND_LONG_VALUE;
+	char buf[BUFSIZE_FGETS], *endp;
+	unsigned int i;
+
+	if (fseek(info->file_vmcoreinfo, 0, SEEK_SET) < 0) {
+		ERRMSG("Can't seek the vmcoreinfo file(%s). %s\n",
+		    info->name_vmcoreinfo, strerror(errno));
+		return INVALID_STRUCTURE_DATA;
+	}
+
+	while (fgets(buf, BUFSIZE_FGETS, info->file_vmcoreinfo)) {
+		i = strlen(buf);
+		if (!i)
+			break;
+		if (buf[i - 1] == '\n')
+			buf[i - 1] = '\0';
+		if (strncmp(buf, str_structure, strlen(str_structure)) == 0) {
+			data = strtoul(buf + strlen(str_structure), &endp, 10);
+			if (strlen(endp) != 0)
+				data = strtoul(buf + strlen(str_structure), &endp, 16);
+			if ((data == LONG_MAX) || strlen(endp) != 0) {
+				ERRMSG("Invalid data in %s: %s",
+				    info->name_vmcoreinfo, buf);
+				return INVALID_STRUCTURE_DATA;
+			}
+			break;
+		}
+	}
+	return data;
+}
+
 long
 read_vmcoreinfo_long(char *str_structure)
 {
diff --git a/makedumpfile.h b/makedumpfile.h
index a5955ff750e5..c5e38a5b6e4b 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -393,6 +393,22 @@ do { \
 			return FALSE; \
 	} \
 } while (0)
+#define WRITE_NUMBER_UNSIGNED(str_number, number) \
+do { \
+	if (NUMBER(number) != NOT_FOUND_NUMBER) { \
+		fprintf(info->file_vmcoreinfo, "%s%lu\n", \
+		    STR_NUMBER(str_number), NUMBER(number)); \
+	} \
+} while (0)
+#define READ_NUMBER_UNSIGNED(str_number, number) \
+do { \
+	if (NUMBER(number) == NOT_FOUND_NUMBER) { \
+		NUMBER(number) = read_vmcoreinfo_ulong(STR_NUMBER(str_number)); \
+		if (NUMBER(number) == INVALID_STRUCTURE_DATA) \
+			return FALSE; \
+	} \
+} while (0)
+
 
 /*
  * for source file name
-- 
2.7.4



From panand at redhat.com  Tue Oct 25 00:22:56 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 12:52:56 +0530
Subject: [PATCH Makedumpfile 04/10] arm64: use already available PAGESIZE()
 and PAGESHIFT() macros
In-Reply-To: <cover.1477378297.git.panand@redhat.com>
References: <cover.1477378297.git.panand@redhat.com>
Message-ID: <640af7cb449683947a23261511e4a9fee0765013.1477378297.git.panand@redhat.com>

Since PAGESIZE() and PAGESHIFT() macros uses page size value from
VMCOREINFO_PAGESIZE() therefore use them instead of hard coding.

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/arm64.c   | 24 +++++++-----------------
 makedumpfile.h |  1 -
 2 files changed, 7 insertions(+), 18 deletions(-)

diff --git a/arch/arm64.c b/arch/arm64.c
index 4a2a9a9ec45d..c73efa1aad54 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -44,14 +44,13 @@ typedef struct {
 #define pmd_val(x)		(pud_val((x).pud))
 #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 PAGE_MASK		(~(PAGESIZE() - 1))
+#define PGDIR_SHIFT		((PAGESHIFT() - 3) * ARM64_PGTABLE_LEVELS + 3)
 #define PUD_SHIFT		PGDIR_SHIFT
 #define PUD_SIZE		(1UL << PUD_SHIFT)
 #define PTRS_PER_PGD		(1 << (VA_BITS - PGDIR_SHIFT))
-#define PTRS_PER_PTE		(1 << (PAGE_SHIFT - 3))
-#define PMD_SHIFT		((PAGE_SHIFT - 3) * 2 + 3)
+#define PTRS_PER_PTE		(1 << (PAGESHIFT() - 3))
+#define PMD_SHIFT		((PAGESHIFT() - 3) * 2 + 3)
 #define PMD_SIZE		(1UL << PMD_SHIFT)
 #define PMD_MASK		(~(PMD_SIZE - 1))
 #define PTRS_PER_PMD		PTRS_PER_PTE
@@ -77,7 +76,7 @@ typedef struct {
 #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(vaddr) 		(((vaddr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_index(vaddr) 		(((vaddr) >> PAGESHIFT()) & (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))
 
@@ -92,14 +91,13 @@ typedef struct {
 #define KERN_STRUCT_PAGE_SIZE		get_structure_size("page", DWARF_INFO_GET_STRUCT_SIZE)
 
 #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 PFN_DOWN(x)			((x) >> PAGESHIFT())
+#define VMEMMAP_SIZE			ALIGN((1UL << (VA_BITS - PAGESHIFT())) * KERN_STRUCT_PAGE_SIZE, PUD_SIZE)
 #define MODULES_END			PAGE_OFFSET
 #define MODULES_VADDR			(MODULES_END - 0x4000000)
 
 static int pgtable_level;
 static int va_bits;
-static int page_shift;
 
 int
 get_pgtable_level_arm64(void)
@@ -113,12 +111,6 @@ get_va_bits_arm64(void)
 	return va_bits;
 }
 
-int
-get_page_shift_arm64(void)
-{
-	return page_shift;
-}
-
 static pmd_t *
 pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
 {
@@ -150,11 +142,9 @@ static int calculate_plat_config(void)
 	if ((stext & PAGE_OFFSET_39) == PAGE_OFFSET_39) {
 		pgtable_level = 3;
 		va_bits = 39;
-		page_shift = 12;
 	} else if ((stext & PAGE_OFFSET_42) == PAGE_OFFSET_42) {
 		pgtable_level = 2;
 		va_bits = 42;
-		page_shift = 16;
 	} else {
 		ERRMSG("Kernel Configuration not supported\n");
 		return FALSE;
diff --git a/makedumpfile.h b/makedumpfile.h
index c5e38a5b6e4b..c363c547b448 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -519,7 +519,6 @@ do { \
 int get_va_bits_arm64(void);
 #define ARM64_PGTABLE_LEVELS	get_pgtable_level_arm64()
 #define VA_BITS			get_va_bits_arm64()
-#define PAGE_SHIFT		get_page_shift_arm64()
 #define KVBASE			VMALLOC_START
 #endif /* aarch64 */
 
-- 
2.7.4



From panand at redhat.com  Tue Oct 25 00:22:57 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 12:52:57 +0530
Subject: [PATCH Makedumpfile 05/10] arm64: fix page_offset definition
In-Reply-To: <cover.1477378297.git.panand@redhat.com>
References: <cover.1477378297.git.panand@redhat.com>
Message-ID: <862a1692521ff11b2dd59e07eec0e9b2c3c253ae.1477378297.git.panand@redhat.com>

arch/arm64/include/asm/memory.h defines PAGE_OFFSET as follows:

 #define PAGE_OFFSET             (UL(0xffffffffffffffff) << (VA_BITS - 1))

Use same definition in makedumpfile as well.

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/arm64.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/arm64.c b/arch/arm64.c
index c73efa1aad54..ce5869452484 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -203,8 +203,7 @@ get_machdep_info_arm64(void)
 {
 	info->max_physmem_bits = PHYS_MASK_SHIFT;
 	info->section_size_bits = SECTIONS_SIZE_BITS;
-	info->page_offset = SYMBOL(_stext)
-		& (0xffffffffffffffffUL << (VA_BITS - 1));
+	info->page_offset = 0xffffffffffffffffUL << (VA_BITS - 1);
 	info->vmalloc_start = 0xffffffffffffffffUL << VA_BITS;
 	info->vmalloc_end = PAGE_OFFSET - PUD_SIZE - VMEMMAP_SIZE - 0x10000;
 	info->vmemmap_start = VMALLOC_END + 0x10000;
-- 
2.7.4



From panand at redhat.com  Tue Oct 25 00:22:58 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 12:52:58 +0530
Subject: [PATCH Makedumpfile 06/10] arm64: fix re-filtering
In-Reply-To: <cover.1477378297.git.panand@redhat.com>
References: <cover.1477378297.git.panand@redhat.com>
Message-ID: <ba6cc8acfb3f60180e7481729217bd4a27f50955.1477378297.git.panand@redhat.com>

get_phys_base() is not called for re-filtering. Therefore,
calculate_plat_config() is never called if re-filtering is enabled.
Otherwise too, it seems more appropriate to call calculate_plat_config() in
get_machdep_info(). Therefore, moving calling of calculate_plat_config()
into get_machdep_info().

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/arm64.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm64.c b/arch/arm64.c
index ce5869452484..a5b1bca43e64 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -171,11 +171,6 @@ get_phys_base_arm64(void)
 	unsigned long long phys_start;
 	int i;
 
-	if (!calculate_plat_config()) {
-		ERRMSG("Can't determine platform config values\n");
-		return FALSE;
-	}
-
 	/*
 	 * We resolve phys_base from PT_LOAD segments. LMA contains physical
 	 * address of the segment, and we use the lowest start as
@@ -201,6 +196,11 @@ get_phys_base_arm64(void)
 int
 get_machdep_info_arm64(void)
 {
+	if (!calculate_plat_config()) {
+		ERRMSG("Can't determine platform config values\n");
+		return FALSE;
+	}
+
 	info->max_physmem_bits = PHYS_MASK_SHIFT;
 	info->section_size_bits = SECTIONS_SIZE_BITS;
 	info->page_offset = 0xffffffffffffffffUL << (VA_BITS - 1);
-- 
2.7.4



From panand at redhat.com  Tue Oct 25 00:22:59 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 12:52:59 +0530
Subject: [PATCH Makedumpfile 07/10] arm64: use value of VA_BITS and
 PHYS_OFFSET embedded into vmcore
In-Reply-To: <cover.1477378297.git.panand@redhat.com>
References: <cover.1477378297.git.panand@redhat.com>
Message-ID: <a1ec87ec550cffcc7b364abc83254f27dde369d0.1477378297.git.panand@redhat.com>

ARM64 kdump-v26 patch (4/7) [1] has embedded VA_BITS and PHYS_OFFSET into
vmcore. Therefore this patch does following improvements:

1) Read value of VA_BITS from vmcore, instead of hard coding.
2) Remove calculation of PHYS_OFFSET from PT_LOAD and read it from vmcore
as well.
3) arch/arm64/Kconfig defines page table levels on the basic of page size and
VA bits. Use same definition in makedumpfile as well.
4) Since pgtable_level and va_bits are used only in arm64.c, therefore get rid
of get_pgtable_level_arm64() and get_va_bits_arm64() function.
5) Since va_bits and pgtable_levels are local to arch/arm64.c, therefore
remove #define of ARM64_PGTABLE_LEVELS and VA_BITS from makedumpfile.h

[1] https://www.mail-archive.com/kexec at lists.infradead.org/msg16298.html

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/arm64.c   | 88 +++++++++++++++++-----------------------------------------
 makedumpfile.c |  8 ++++++
 makedumpfile.h |  7 +++--
 3 files changed, 38 insertions(+), 65 deletions(-)

diff --git a/arch/arm64.c b/arch/arm64.c
index a5b1bca43e64..6f61b4c5497f 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -39,16 +39,23 @@ typedef struct {
 	unsigned long pte;
 } pte_t;
 
+static int pgtable_level;
+static int va_bits;
+
+#define SZ_4K			(4 * 1024)
+#define SZ_16K			(16 * 1024)
+#define SZ_64K			(64 * 1024)
+
 #define pgd_val(x)		((x).pgd)
 #define pud_val(x)		(pgd_val((x).pgd))
 #define pmd_val(x)		(pud_val((x).pud))
 #define pte_val(x)		((x).pte)
 
 #define PAGE_MASK		(~(PAGESIZE() - 1))
-#define PGDIR_SHIFT		((PAGESHIFT() - 3) * ARM64_PGTABLE_LEVELS + 3)
+#define PGDIR_SHIFT		((PAGESHIFT() - 3) * pgtable_level + 3)
 #define PUD_SHIFT		PGDIR_SHIFT
 #define PUD_SIZE		(1UL << PUD_SHIFT)
-#define PTRS_PER_PGD		(1 << (VA_BITS - PGDIR_SHIFT))
+#define PTRS_PER_PGD		(1 << (va_bits - PGDIR_SHIFT))
 #define PTRS_PER_PTE		(1 << (PAGESHIFT() - 3))
 #define PMD_SHIFT		((PAGESHIFT() - 3) * 2 + 3)
 #define PMD_SIZE		(1UL << PMD_SHIFT)
@@ -92,25 +99,10 @@ typedef struct {
 
 #define ALIGN(x, a) 			(((x) + (a) - 1) & ~((a) - 1))
 #define PFN_DOWN(x)			((x) >> PAGESHIFT())
-#define VMEMMAP_SIZE			ALIGN((1UL << (VA_BITS - PAGESHIFT())) * KERN_STRUCT_PAGE_SIZE, PUD_SIZE)
+#define VMEMMAP_SIZE			ALIGN((1UL << (va_bits - PAGESHIFT())) * KERN_STRUCT_PAGE_SIZE, PUD_SIZE)
 #define MODULES_END			PAGE_OFFSET
 #define MODULES_VADDR			(MODULES_END - 0x4000000)
 
-static int pgtable_level;
-static int va_bits;
-
-int
-get_pgtable_level_arm64(void)
-{
-	return pgtable_level;
-}
-
-int
-get_va_bits_arm64(void)
-{
-	return va_bits;
-}
-
 static pmd_t *
 pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
 {
@@ -121,32 +113,23 @@ pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
 	}
 }
 
-#define PAGE_OFFSET_39 (0xffffffffffffffffUL << 39)
-#define PAGE_OFFSET_42 (0xffffffffffffffffUL << 42)
 static int calculate_plat_config(void)
 {
-	unsigned long long stext;
-
-	/* Currently we assume that there are only two possible
-	 * configuration supported by kernel.
-	 * 1) Page Table Level:2, Page Size 64K and VA Bits 42
-	 * 1) Page Table Level:3, Page Size 4K and VA Bits 39
-	 * Ideally, we should have some mechanism to decide these values
-	 * from kernel symbols, but we have limited symbols in vmcore,
-	 * and we can not do much. So until some one comes with a better
-	 * way, we use following.
-	 */
-	stext = SYMBOL(_stext);
+	va_bits = NUMBER(VA_BITS);
 
-	/* condition for minimum VA bits must be checked first and so on */
-	if ((stext & PAGE_OFFSET_39) == PAGE_OFFSET_39) {
-		pgtable_level = 3;
-		va_bits = 39;
-	} else if ((stext & PAGE_OFFSET_42) == PAGE_OFFSET_42) {
+	/* derive pgtable_level as per arch/arm64/Kconfig */
+	if ((PAGESIZE() == SZ_16K && va_bits == 36) ||
+			(PAGESIZE() == SZ_64K && va_bits == 42)) {
 		pgtable_level = 2;
-		va_bits = 42;
+	} else if ((PAGESIZE() == SZ_64K && va_bits == 48) ||
+			(PAGESIZE() == SZ_4K && va_bits == 39) ||
+			(PAGESIZE() == SZ_16K && va_bits == 47)) {
+		pgtable_level = 3;
+	} else if ((PAGESIZE() != SZ_64K && va_bits == 48)) {
+		pgtable_level = 4;
 	} else {
-		ERRMSG("Kernel Configuration not supported\n");
+		ERRMSG("PAGE SIZE %#lx and VA Bits %d not supported\n",
+				PAGESIZE(), va_bits);
 		return FALSE;
 	}
 
@@ -167,28 +150,9 @@ is_vtop_from_page_table_arm64(unsigned long vaddr)
 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;
+	info->phys_base = NUMBER(PHYS_OFFSET);
 
-	DEBUG_MSG("phys_base    : %lx\n", phys_base);
+	DEBUG_MSG("phys_base    : %lx\n", info->phys_base);
 
 	return TRUE;
 }
@@ -203,8 +167,8 @@ get_machdep_info_arm64(void)
 
 	info->max_physmem_bits = PHYS_MASK_SHIFT;
 	info->section_size_bits = SECTIONS_SIZE_BITS;
-	info->page_offset = 0xffffffffffffffffUL << (VA_BITS - 1);
-	info->vmalloc_start = 0xffffffffffffffffUL << VA_BITS;
+	info->page_offset = 0xffffffffffffffffUL << (va_bits - 1);
+	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;
diff --git a/makedumpfile.c b/makedumpfile.c
index e248db876858..df413f066348 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -2263,6 +2263,10 @@ write_vmcoreinfo_data(void)
 	WRITE_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE);
 
 	WRITE_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
+#ifdef __aarch64__
+	WRITE_NUMBER("VA_BITS", VA_BITS);
+	WRITE_NUMBER_UNSIGNED("PHYS_OFFSET", PHYS_OFFSET);
+#endif
 
 	/*
 	 * write the source file of 1st kernel
@@ -2645,6 +2649,10 @@ read_vmcoreinfo(void)
 
 	READ_NUMBER("PAGE_BUDDY_MAPCOUNT_VALUE", PAGE_BUDDY_MAPCOUNT_VALUE);
 	READ_NUMBER("KERNEL_IMAGE_SIZE", KERNEL_IMAGE_SIZE);
+#ifdef __aarch64__
+	READ_NUMBER("VA_BITS", VA_BITS);
+	READ_NUMBER_UNSIGNED("PHYS_OFFSET", PHYS_OFFSET);
+#endif
 
 	READ_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
 
diff --git a/makedumpfile.h b/makedumpfile.h
index c363c547b448..1a119ac949b6 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -516,9 +516,6 @@ do { \
 #define PMASK			(0x7ffffffffffff000UL)
 
 #ifdef __aarch64__
-int get_va_bits_arm64(void);
-#define ARM64_PGTABLE_LEVELS	get_pgtable_level_arm64()
-#define VA_BITS			get_va_bits_arm64()
 #define KVBASE			VMALLOC_START
 #endif /* aarch64 */
 
@@ -1736,6 +1733,10 @@ struct number_table {
 	long	SECTION_SIZE_BITS;
 	long	MAX_PHYSMEM_BITS;
 	long    HUGETLB_PAGE_DTOR;
+#ifdef __aarch64__
+	long 	VA_BITS;
+	unsigned long	PHYS_OFFSET;
+#endif
 };
 
 struct srcfile_table {
-- 
2.7.4



From panand at redhat.com  Tue Oct 25 00:23:00 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 12:53:00 +0530
Subject: [PATCH Makedumpfile 08/10] arm64: immunize identity mapped address
 finding w.r.t. kernel changes
In-Reply-To: <cover.1477378297.git.panand@redhat.com>
References: <cover.1477378297.git.panand@redhat.com>
Message-ID: <077c409cd377c4ca59b92aa71611d97016a92639.1477378297.git.panand@redhat.com>

Kernel mappings may change for vmalloc, vmemmap and module addresses. More
over, proposed kexec arm64 kernel patches do not provide sufficient
information in vmcore to separate out these areas.

Makedumpfile should be able to read entries from swapper page tables
minimally. Virtual address of swapper_pg_dir symbol will always be linearly
translatable. So, using __pa() macro we get physical address of
swapper_pg_dir and then we find physical address of any kernel virtual
address by reading corresponding entries in page table.

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/arm64.c   | 75 +++++++++++++---------------------------------------------
 makedumpfile.h |  3 ++-
 2 files changed, 19 insertions(+), 59 deletions(-)

diff --git a/arch/arm64.c b/arch/arm64.c
index 6f61b4c5497f..da8f43c62380 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -53,8 +53,6 @@ static int va_bits;
 
 #define PAGE_MASK		(~(PAGESIZE() - 1))
 #define PGDIR_SHIFT		((PAGESHIFT() - 3) * pgtable_level + 3)
-#define PUD_SHIFT		PGDIR_SHIFT
-#define PUD_SIZE		(1UL << PUD_SHIFT)
 #define PTRS_PER_PGD		(1 << (va_bits - PGDIR_SHIFT))
 #define PTRS_PER_PTE		(1 << (PAGESHIFT() - 3))
 #define PMD_SHIFT		((PAGESHIFT() - 3) * 2 + 3)
@@ -77,31 +75,19 @@ static int va_bits;
 #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(vaddr) 		(((vaddr) >> PAGESHIFT()) & (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))
+#define pmd_page_paddr(pmd)		(pmd_val(pmd) & PHYS_MASK & (int32_t)PAGE_MASK)
+#define pte_offset(dir, vaddr) 		((pte_t*)pmd_page_paddr((*dir)) + pte_index(vaddr))
 
 #define pmd_index(vaddr)		(((vaddr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
-#define pud_page_vaddr(pud)		(__va(pud_val(pud) & PHYS_MASK & (int32_t)PAGE_MASK))
+#define pud_page_paddr(pud)		(pud_val(pud) & PHYS_MASK & (int32_t)PAGE_MASK)
 #define pmd_offset_pgtbl_lvl_2(pud, vaddr) ((pmd_t *)pud)
-#define pmd_offset_pgtbl_lvl_3(pud, vaddr) ((pmd_t *)pud_page_vaddr((*pud)) + pmd_index(vaddr))
-
-/* kernel struct page size can be kernel version dependent, currently
- * keep it constant.
- */
-#define KERN_STRUCT_PAGE_SIZE		get_structure_size("page", DWARF_INFO_GET_STRUCT_SIZE)
-
-#define ALIGN(x, a) 			(((x) + (a) - 1) & ~((a) - 1))
-#define PFN_DOWN(x)			((x) >> PAGESHIFT())
-#define VMEMMAP_SIZE			ALIGN((1UL << (va_bits - PAGESHIFT())) * KERN_STRUCT_PAGE_SIZE, PUD_SIZE)
-#define MODULES_END			PAGE_OFFSET
-#define MODULES_VADDR			(MODULES_END - 0x4000000)
+#define pmd_offset_pgtbl_lvl_3(pud, vaddr) ((pmd_t *)pud_page_paddr((*pud)) + pmd_index(vaddr))
 
 static pmd_t *
 pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
@@ -136,15 +122,10 @@ static int calculate_plat_config(void)
 	return TRUE;
 }
 
-static int
-is_vtop_from_page_table_arm64(unsigned long vaddr)
+unsigned long
+get_kvbase_arm64(void)
 {
-	/* 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));
+	return (0xffffffffffffffffUL << va_bits);
 }
 
 int
@@ -168,20 +149,10 @@ get_machdep_info_arm64(void)
 	info->max_physmem_bits = PHYS_MASK_SHIFT;
 	info->section_size_bits = SECTIONS_SIZE_BITS;
 	info->page_offset = 0xffffffffffffffffUL << (va_bits - 1);
-	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;
 }
@@ -211,17 +182,18 @@ get_versiondep_info_arm64(void)
 }
 
 /*
- * vtop_arm64() - translate arbitrary virtual address to physical
+ * vaddr_to_paddr_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
+vaddr_to_paddr_arm64(unsigned long vaddr)
 {
 	unsigned long long paddr = NOT_PADDR;
+	unsigned long long swapper_phys;
 	pgd_t	*pgda, pgdv;
 	pud_t	*puda, pudv;
 	pmd_t	*pmda, pmdv;
@@ -232,8 +204,10 @@ vtop_arm64(unsigned long vaddr)
 		return NOT_PADDR;
 	}
 
-	pgda = pgd_offset(SYMBOL(swapper_pg_dir), vaddr);
-	if (!readmem(VADDR, (unsigned long long)pgda, &pgdv, sizeof(pgdv))) {
+	swapper_phys = __pa(SYMBOL(swapper_pg_dir));
+
+	pgda = pgd_offset(swapper_phys, vaddr);
+	if (!readmem(PADDR, (unsigned long long)pgda, &pgdv, sizeof(pgdv))) {
 		ERRMSG("Can't read pgd\n");
 		return NOT_PADDR;
 	}
@@ -242,7 +216,7 @@ vtop_arm64(unsigned long vaddr)
 	puda = (pud_t *)pgda;
 
 	pmda = pmd_offset(puda, &pudv, vaddr);
-	if (!readmem(VADDR, (unsigned long long)pmda, &pmdv, sizeof(pmdv))) {
+	if (!readmem(PADDR, (unsigned long long)pmda, &pmdv, sizeof(pmdv))) {
 		ERRMSG("Can't read pmd\n");
 		return NOT_PADDR;
 	}
@@ -251,7 +225,7 @@ vtop_arm64(unsigned long vaddr)
 	case PMD_TYPE_TABLE:
 		ptea = pte_offset(&pmdv, vaddr);
 		/* 64k page */
-		if (!readmem(VADDR, (unsigned long long)ptea, &ptev, sizeof(ptev))) {
+		if (!readmem(PADDR, (unsigned long long)ptea, &ptev, sizeof(ptev))) {
 			ERRMSG("Can't read pte\n");
 			return NOT_PADDR;
 		}
@@ -275,19 +249,4 @@ vtop_arm64(unsigned long vaddr)
 	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 /* __aarch64__ */
diff --git a/makedumpfile.h b/makedumpfile.h
index 1a119ac949b6..8ddc2c43cc29 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -516,7 +516,8 @@ do { \
 #define PMASK			(0x7ffffffffffff000UL)
 
 #ifdef __aarch64__
-#define KVBASE			VMALLOC_START
+unsigned long get_kvbase_arm64(void);
+#define KVBASE			get_kvbase_arm64()
 #endif /* aarch64 */
 
 #ifdef __arm__
-- 
2.7.4



From panand at redhat.com  Tue Oct 25 00:23:01 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 12:53:01 +0530
Subject: [PATCH Makedumpfile 09/10] arm64: Add support for 4level 4K page
 translations table
In-Reply-To: <cover.1477378297.git.panand@redhat.com>
References: <cover.1477378297.git.panand@redhat.com>
Message-ID: <4f49772bb95a91fb42f962769fd96d07e1eb57ef.1477378297.git.panand@redhat.com>

From: Azriel Samson <asamson at codeaurora.org>

Add PUD translation for 4 level page tables.

Signed-off-by: Mansi Patel <mansip at codeaurora.org>
Signed-off-by: Azriel Samson <asamson at codeaurora.org>
Signed-off-by: Sameer Goel <sgoel at codeaurora.org>
Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/arm64.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/arch/arm64.c b/arch/arm64.c
index da8f43c62380..df58e92536e2 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -54,7 +54,9 @@ static int va_bits;
 #define PAGE_MASK		(~(PAGESIZE() - 1))
 #define PGDIR_SHIFT		((PAGESHIFT() - 3) * pgtable_level + 3)
 #define PTRS_PER_PGD		(1 << (va_bits - PGDIR_SHIFT))
+#define PUD_SHIFT		get_pud_shift_arm64()
 #define PTRS_PER_PTE		(1 << (PAGESHIFT() - 3))
+#define PTRS_PER_PUD		PTRS_PER_PTE
 #define PMD_SHIFT		((PAGESHIFT() - 3) * 2 + 3)
 #define PMD_SIZE		(1UL << PMD_SHIFT)
 #define PMD_MASK		(~(PMD_SIZE - 1))
@@ -89,6 +91,18 @@ static int va_bits;
 #define pmd_offset_pgtbl_lvl_2(pud, vaddr) ((pmd_t *)pud)
 #define pmd_offset_pgtbl_lvl_3(pud, vaddr) ((pmd_t *)pud_page_paddr((*pud)) + pmd_index(vaddr))
 
+#define pud_index(vaddr)		(((vaddr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
+#define pgd_page_paddr(pgd)		(pgd_val(pgd) & PHYS_MASK & (int32_t)PAGE_MASK)
+
+static int
+get_pud_shift_arm64(void)
+{
+	if (pgtable_level == 4)
+		return ((PAGESHIFT() - 3) * 3 + 3);
+	else
+		return PGDIR_SHIFT;
+}
+
 static pmd_t *
 pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
 {
@@ -99,6 +113,15 @@ pmd_offset(pud_t *puda, pud_t *pudv, unsigned long vaddr)
 	}
 }
 
+static pud_t *
+pud_offset(pgd_t *pgda, pgd_t *pgdv, unsigned long vaddr)
+{
+	if (pgtable_level == 4)
+		return ((pud_t *)pgd_page_paddr((*pgdv)) + pud_index(vaddr));
+	else
+		return (pud_t *)(pgda);
+}
+
 static int calculate_plat_config(void)
 {
 	va_bits = NUMBER(VA_BITS);
@@ -212,8 +235,11 @@ vaddr_to_paddr_arm64(unsigned long vaddr)
 		return NOT_PADDR;
 	}
 
-	pudv.pgd = pgdv;
-	puda = (pud_t *)pgda;
+	puda = pud_offset(pgda, &pgdv, vaddr);
+	if (!readmem(PADDR, (unsigned long long)puda, &pudv, sizeof(pudv))) {
+		ERRMSG("Can't read pud\n");
+		return NOT_PADDR;
+	}
 
 	pmda = pmd_offset(puda, &pudv, vaddr);
 	if (!readmem(PADDR, (unsigned long long)pmda, &pmdv, sizeof(pmdv))) {
-- 
2.7.4



From panand at redhat.com  Tue Oct 25 00:23:02 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 12:53:02 +0530
Subject: [PATCH Makedumpfile 10/10] arm64: fix memory layout as per changes in
 v4.6 kernel
In-Reply-To: <cover.1477378297.git.panand@redhat.com>
References: <cover.1477378297.git.panand@redhat.com>
Message-ID: <ea2b61be816105c177f31f60c473cf0be4720bfb.1477378297.git.panand@redhat.com>

arm64 memory layout has been changed since 4.6 kernel because of KASLR
support patches.

kimage_voffset is needed to calculate "virtual to physical".

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/arm64.c   | 16 ++++++++++++++--
 makedumpfile.c |  2 ++
 makedumpfile.h |  1 +
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/arch/arm64.c b/arch/arm64.c
index df58e92536e2..958f57f8e203 100644
--- a/arch/arm64.c
+++ b/arch/arm64.c
@@ -41,10 +41,12 @@ typedef struct {
 
 static int pgtable_level;
 static int va_bits;
+static unsigned long kimage_voffset;
 
 #define SZ_4K			(4 * 1024)
 #define SZ_16K			(16 * 1024)
 #define SZ_64K			(64 * 1024)
+#define SZ_128M			(128 * 1024 * 1024)
 
 #define pgd_val(x)		((x).pgd)
 #define pud_val(x)		(pgd_val((x).pgd))
@@ -77,8 +79,6 @@ static int va_bits;
 #define PMD_TYPE_SECT		1
 #define PMD_TYPE_TABLE		3
 
-#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))
 
@@ -94,6 +94,16 @@ static int va_bits;
 #define pud_index(vaddr)		(((vaddr) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
 #define pgd_page_paddr(pgd)		(pgd_val(pgd) & PHYS_MASK & (int32_t)PAGE_MASK)
 
+static unsigned long long
+__pa(unsigned long vaddr)
+{
+	if (kimage_voffset == NOT_FOUND_NUMBER ||
+			(vaddr >= PAGE_OFFSET))
+		return (vaddr - PAGE_OFFSET + info->phys_base);
+	else
+		return (vaddr - kimage_voffset);
+}
+
 static int
 get_pud_shift_arm64(void)
 {
@@ -169,10 +179,12 @@ get_machdep_info_arm64(void)
 		return FALSE;
 	}
 
+	kimage_voffset = NUMBER(kimage_voffset);
 	info->max_physmem_bits = PHYS_MASK_SHIFT;
 	info->section_size_bits = SECTIONS_SIZE_BITS;
 	info->page_offset = 0xffffffffffffffffUL << (va_bits - 1);
 
+	DEBUG_MSG("kimage_voffset   : %lx\n", kimage_voffset);
 	DEBUG_MSG("max_physmem_bits : %lx\n", info->max_physmem_bits);
 	DEBUG_MSG("section_size_bits: %lx\n", info->section_size_bits);
 	DEBUG_MSG("page_offset      : %lx\n", info->page_offset);
diff --git a/makedumpfile.c b/makedumpfile.c
index df413f066348..1fa9a63359c4 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -2266,6 +2266,7 @@ write_vmcoreinfo_data(void)
 #ifdef __aarch64__
 	WRITE_NUMBER("VA_BITS", VA_BITS);
 	WRITE_NUMBER_UNSIGNED("PHYS_OFFSET", PHYS_OFFSET);
+	WRITE_NUMBER_UNSIGNED("kimage_voffset", kimage_voffset);
 #endif
 
 	/*
@@ -2652,6 +2653,7 @@ read_vmcoreinfo(void)
 #ifdef __aarch64__
 	READ_NUMBER("VA_BITS", VA_BITS);
 	READ_NUMBER_UNSIGNED("PHYS_OFFSET", PHYS_OFFSET);
+	READ_NUMBER_UNSIGNED("kimage_voffset", kimage_voffset);
 #endif
 
 	READ_NUMBER("HUGETLB_PAGE_DTOR", HUGETLB_PAGE_DTOR);
diff --git a/makedumpfile.h b/makedumpfile.h
index 8ddc2c43cc29..f0154226bcb8 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -1737,6 +1737,7 @@ struct number_table {
 #ifdef __aarch64__
 	long 	VA_BITS;
 	unsigned long	PHYS_OFFSET;
+	unsigned long	kimage_voffset;
 #endif
 };
 
-- 
2.7.4



From louis.bouchard at canonical.com  Tue Oct 25 01:59:23 2016
From: louis.bouchard at canonical.com (Louis Bouchard)
Date: Tue, 25 Oct 2016 10:59:23 +0200
Subject: makedumpfile issues many readpage_elf: Attempt to read
 non-existent page
In-Reply-To: <CAL0thcP2Pp43nWLJ_jfwDQnW4RNRpP27fpymQ8pPtORPaeX8nQ@mail.gmail.com>
References: <57E3DCDB.5020308@canonical.com>
 <0910DD04CBD6DE4193FCF86B9C00BE9701E6B42E@BPXM01GP.gisp.nec.co.jp>
 <57ED187D.3040007@canonical.com>
 <CAL0thcP2Pp43nWLJ_jfwDQnW4RNRpP27fpymQ8pPtORPaeX8nQ@mail.gmail.com>
Message-ID: <161d0e6f-5b1c-dfa9-aa28-5393e2a86d1d@canonical.com>

Good morning,

Le 24/10/2016 ? 16:54, Louis Bouchard a ?crit :
> Hello,
>
> Le 29/09/2016 ? 15:34, Louis Bouchard a ?crit :
>> Hello,
>>
>> Le 23/09/2016 14:04, Atsushi Kumagai a ?crit :
>>>> Does someone have an idea of where this could come from ?
>>>
>>> Thanks for your report, but I'm afraid that I'm going on
>>> vacation till Oct 2.
>>> I hope someone helps you until I'm back.
>>>
>>>
>>> Regards,
>>> Atsushi Kumagai
>>>
>>
>> As a follow up to my question, I've been investigating the issue. The source of
>> the problem seems to come from readpage_elf() which tries to read to an
>> inexistant page :
>>
>> readpage_elf: Attempt to read non-existent page at 0x1a7b7fff5000.
>>
>> The error happens when readpage_elf() is called from section_mem_map_addr with
>> pgaddr, which is derived from paddr. This one comes from :
>>
>>    paddr = vaddr_to_paddr(addr)
>>
>> When tracing vaddr_to_paddr, I see a difference in the calculation. on a 4.4
>> kernel :
>>
>>   info->phys_base = 0
>>
>> On 4.8 :
>>   info->phys_base = 0xffffffffe3800000
>>
>> So the paddr values used to define pgaddr are :
>>
>> for 4.4 kernels : 0x3fff4000
>> for 4.8 kernels : 0x1a7b7fff5000
>>
>> Running makedumpfile --dump-dmesg in debug mode leads to :
>>
>> 4.4 kernel :
>>
>> sadump: does not have partition header
>> sadump: read dump device as unknown format
>> sadump: unknown format
>> LOAD (0)
>>   phys_start : 1000000
>>   phys_end   : 2224000
>>   virt_start : ffffffff81000000
>>   virt_end   : ffffffff82224000
>> LOAD (1)
>>   phys_start : 1000
>>   phys_end   : 9fc00
>>   virt_start : ffff880000001000
>>   virt_end   : ffff88000009fc00
>> LOAD (2)
>>   phys_start : 100000
>>   phys_end   : 2b000000
>>   virt_start : ffff880000100000
>>   virt_end   : ffff88002b000000
>> LOAD (3)
>>   phys_start : 33000000
>>   phys_end   : 3fffe000
>>   virt_start : ffff880033000000
>>   virt_end   : ffff88003fffe000
>> Linux kdump
>> page_size    : 4096
>>
>> max_mapnr    : 3fffe
>>
>> Buffer size for the cyclic mode: 65535
>>
>> num of NODEs : 1
>>
>>
>> Memory type  : SPARSEMEM_EX
>>
>> mem_map (0)
>>   mem_map    : ffffea0000000000
>>   pfn_start  : 0
>>   pfn_end    : 8000
>> mem_map (1)
>>   mem_map    : ffffea0000200000
>>   pfn_start  : 8000
>>   pfn_end    : 10000
>> mem_map (2)
>>   mem_map    : ffffea0000400000
>>   pfn_start  : 10000
>>   pfn_end    : 18000
>> mem_map (3)
>>   mem_map    : ffffea0000600000
>>   pfn_start  : 18000
>>   pfn_end    : 20000
>> mem_map (4)
>>   mem_map    : ffffea0000800000
>>   pfn_start  : 20000
>>   pfn_end    : 28000
>> mem_map (5)
>>   mem_map    : ffffea0000a00000
>>   pfn_start  : 28000
>>   pfn_end    : 30000
>> mem_map (6)
>>   mem_map    : ffffea0000c00000
>>   pfn_start  : 30000
>>   pfn_end    : 38000
>> mem_map (7)
>>   mem_map    : ffffea0000e00000
>>   pfn_start  : 38000
>>   pfn_end    : 3fffe
>> mmap() is available on the kernel.
>>
>> log_buf       : ffffffff8210521c
>> log_end       : 0
>> log_buf_len   : 262144
>> log_first_idx : 0
>> log_next_idx  : 141176
>>
>> The dmesg log is saved to /tmp/titi.
>>
>> makedumpfile Completed.
>>
>>
>> For 4.8 kernels :
>> sadump: does not have partition header
>> sadump: read dump device as unknown format
>> sadump: unknown format
>> LOAD (0)
>>   phys_start : 7200000
>>   phys_end   : 847d000
>>   virt_start : ffffffffa3a00000
>>   virt_end   : ffffffffa4c7d000
>> LOAD (1)
>>   phys_start : 1000
>>   phys_end   : 9fc00
>>   virt_start : ffff880000001000
>>   virt_end   : ffff88000009fc00
>> LOAD (2)
>>   phys_start : 100000
>>   phys_end   : 2b000000
>>   virt_start : ffff880000100000
>>   virt_end   : ffff88002b000000
>> LOAD (3)
>>   phys_start : 33000000
>>   phys_end   : 3fffe000
>>   virt_start : ffff880033000000
>>   virt_end   : ffff88003fffe000
>> Linux kdump
>> page_size    : 4096
>>
>> max_mapnr    : 3fffe
>>
>> Buffer size for the cyclic mode: 65535
>> The kernel version is not supported.
>> The makedumpfile operation may be incomplete.
>>
>> num of NODEs : 1
>>
>>
>> Memory type  : SPARSEMEM_EX
>>
>> mem_map (0)
>>   mem_map    : 0
>>   pfn_start  : 0
>>   pfn_end    : 8000
>> mem_map (1)
>>   mem_map    : 0
>>   pfn_start  : 8000
>>   pfn_end    : 10000
>> mem_map (2)
>>   mem_map    : 0
>>   pfn_start  : 10000
>>   pfn_end    : 18000
>> mem_map (3)
>>   mem_map    : 0
>>   pfn_start  : 18000
>>   pfn_end    : 20000
>> mem_map (4)
>>   mem_map    : 0
>>   pfn_start  : 20000
>>   pfn_end    : 28000
>> mem_map (5)
>>   mem_map    : 0
>>   pfn_start  : 28000
>>   pfn_end    : 30000
>> mem_map (6)
>>   mem_map    : 0
>>   pfn_start  : 30000
>>   pfn_end    : 38000
>> mem_map (7)
>>   mem_map    : 0
>>   pfn_start  : 38000
>>   pfn_end    : 3fffe
>> mmap() is available on the kernel.
>>
>> log_buf       : ffffffffa4b3c19c
>> log_end       : 0
>> log_buf_len   : 262144
>> log_first_idx : 0
>> log_next_idx  : 43160
>>
>> The dmesg log is saved to /tmp/toto.
>>
>> makedumpfile Completed.
>>
>>
>> I don't know if it is to be expected with kernels 4.8 to have all mem_map
>> addresses set to 0, unlike with k4.4 :
>>
>> mem_map (0)
>> mem_map : 0
>> pfn_start : 0
>> pfn_end : 8000
>>
>> Any comment appreciated while I continue to investigate.
>>
>> Kind regards,
>>
>> ...Louis
>>
>
> I have now completed the kernel bisection between 4.7.8 and 4.8-rc1 and
> identified the kernel modification that triggers the errors cited above :
>
>> commit 021182e52fe01c1f7b126f97fd6ba048dc4234fd
>> Author: Thomas Garnier <thgarnie at google.com>
>> Date:   Tue Jun 21 17:47:03 2016 -0700
>>
>>     x86/mm: Enable KASLR for physical mapping memory regions
>>
>>     Add the physical mapping in the list of randomized memory regions.
>>
>>     The physical memory mapping holds most allocations from boot and heap
>>     allocators. Knowing the base address and physical memory size, an attacker
>>     can deduce the PDE virtual address for the vDSO memory page. This attack
>>     was demonstrated at CanSecWest 2016, in the following presentation:
>>
>>       "Getting Physical: Extreme Abuse of Intel Based Paged Systems":
>>       https://github.com/n3k/CansecWest2016_Getting_Physical_Extreme_Abuse_of_Intel_Based_Paging_Systems/blob/master/Presentation/CanSec2016_Presentation.pdf
>>
>>     (See second part of the presentation).
>>
>>     The exploits used against Linux worked successfully against 4.6+ but
>>     fail with KASLR memory enabled:
>>
>>       https://github.com/n3k/CansecWest2016_Getting_Physical_Extreme_Abuse_of_Intel_Based_Paging_Systems/tree/master/Demos/Linux/exploits
>>
>>     Similar research was done at Google leading to this patch proposal.
>>
>>     Variants exists to overwrite /proc or /sys objects ACLs leading to
>>     elevation of privileges. These variants were tested against 4.6+.
>>
>>     The page offset used by the compressed kernel retains the static value
>>     since it is not yet randomized during this boot stage.
>>
>>     Signed-off-by: Thomas Garnier <thgarnie at google.com>
>>     Signed-off-by: Kees Cook <keescook at chromium.org>
>>     Cc: Alexander Kuleshov <kuleshovmail at gmail.com>
> <truncated>
>
> The interesting change seems to be :
>
>> -#define __PAGE_OFFSET           _AC(0xffff880000000000, UL)
>> +#define __PAGE_OFFSET_BASE      _AC(0xffff880000000000, UL)
>> +#ifdef CONFIG_RANDOMIZE_MEMORY
>> +#define __PAGE_OFFSET           page_offset_base
>> +#else
>> +#define __PAGE_OFFSET           __PAGE_OFFSET_BASE
>> +#endif /* CONFIG_RANDOMIZE_MEMORY */
>
> I'll try to see if I can fix that.
>
> Kind regards,
>
> ...Louis
>
>
>
>

Some more *important* information in this mostly monologue thread : Pratyush
Anand has pushed a patch to the list earlier today that apparently fixes this
issue :

[PATCH Makedumpfile 1/4] x86_64: Calculate page_offset from pt_load[1]

HTH,

Kind regards,

...Louis

[1] https://www.mail-archive.com/kexec at lists.infradead.org/msg16628.html
-- 
Louis Bouchard
Software engineer, Cloud & Sustaining eng.
Canonical Ltd
Ubuntu developer                       Debian Maintainer
GPG : 429D 7A3B DD05 B6F8 AF63  B9C4 8B3D 867C 823E 7A61


From louis.bouchard at canonical.com  Tue Oct 25 02:17:00 2016
From: louis.bouchard at canonical.com (Louis Bouchard)
Date: Tue, 25 Oct 2016 11:17:00 +0200
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <cover.1477327674.git.panand@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
Message-ID: <0a183cab-17a4-614c-122e-462a4fc08bd5@canonical.com>

Hello,

Le 24/10/2016 ? 18:48, Pratyush Anand a ?crit :
> Patch 1/4 fixes page_offset calculation, so that it is correctly calculated
> on KASLR enabled kernel as well.
> Patch 2/4 simplifies VA to PA translation. New code has been benchmarked
> against old code on a 4T system.
> Patch 3/4 and 4/4 is removal of (now) unnecessary code.
> 
> I think, we should find a way to kill find_vememmap() as well, so that
> VMEMMAP_START can be removed. I have very limited idea about x86, so unable
> to do that as of now.
> 
> Pratyush Anand (4):
>   x86_64: Calculate page_offset from pt_load
>   x86_64: translate all VA to PA using page table values
>   x86_64: kill is_vmalloc_addr_x86_64()
>   x86_64: kill some unused initialization
> 
>  arch/x86_64.c  | 84 ++++++++++++++++++++--------------------------------------
>  makedumpfile.h |  9 +++----
>  2 files changed, 32 insertions(+), 61 deletions(-)
> 

Cross-posting but FYI, this patch fixes the issue reported in the following
thread : makedumpfile issues many readpage_elf: Attempt to read non-existent page[1]

It corresponds to the commit identified by my kernel bisection.

I will wait until it is accepted in Kumagai-san's tree to include it in
Debian/Ubuntu.

Kind regards,

...Louis

[1] https://www.mail-archive.com/kexec at lists.infradead.org/msg16434.html
-- 
Louis Bouchard
Software engineer, Cloud & Sustaining eng.
Canonical Ltd
Ubuntu developer                       Debian Maintainer
GPG : 429D 7A3B DD05 B6F8 AF63  B9C4 8B3D 867C 823E 7A61


From panand at redhat.com  Tue Oct 25 02:20:38 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 14:50:38 +0530
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <0a183cab-17a4-614c-122e-462a4fc08bd5@canonical.com>
References: <cover.1477327674.git.panand@redhat.com>
 <0a183cab-17a4-614c-122e-462a4fc08bd5@canonical.com>
Message-ID: <CAHB_GupmKc-JyG2XBFHqeRBy1HbdCzbY3U2GD76Fyh_fREhpyA@mail.gmail.com>

Hi Louis,

On Tue, Oct 25, 2016 at 2:47 PM, Louis Bouchard
<louis.bouchard at canonical.com> wrote:
> Hello,
>
> Le 24/10/2016 ? 18:48, Pratyush Anand a ?crit :
>> Patch 1/4 fixes page_offset calculation, so that it is correctly calculated
>> on KASLR enabled kernel as well.
>> Patch 2/4 simplifies VA to PA translation. New code has been benchmarked
>> against old code on a 4T system.
>> Patch 3/4 and 4/4 is removal of (now) unnecessary code.
>>
>> I think, we should find a way to kill find_vememmap() as well, so that
>> VMEMMAP_START can be removed. I have very limited idea about x86, so unable
>> to do that as of now.
>>
>> Pratyush Anand (4):
>>   x86_64: Calculate page_offset from pt_load
>>   x86_64: translate all VA to PA using page table values
>>   x86_64: kill is_vmalloc_addr_x86_64()
>>   x86_64: kill some unused initialization
>>
>>  arch/x86_64.c  | 84 ++++++++++++++++++++--------------------------------------
>>  makedumpfile.h |  9 +++----
>>  2 files changed, 32 insertions(+), 61 deletions(-)
>>
>
> Cross-posting but FYI, this patch fixes the issue reported in the following
> thread : makedumpfile issues many readpage_elf: Attempt to read non-existent page[1]
>
> It corresponds to the commit identified by my kernel bisection.
>
> I will wait until it is accepted in Kumagai-san's tree to include it in
> Debian/Ubuntu.

Thanks a lot for your testing.

~Pratyush


From ats-kumagai at wm.jp.nec.com  Tue Oct 25 02:20:28 2016
From: ats-kumagai at wm.jp.nec.com (Atsushi Kumagai)
Date: Tue, 25 Oct 2016 09:20:28 +0000
Subject: [PATCH Makedumpfile 2/4] x86_64: translate all VA to PA using
 page table values
In-Reply-To: <b54b1e73bc4302fa7222c44a9cf46d57aa93b8ba.1477327674.git.panand@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <b54b1e73bc4302fa7222c44a9cf46d57aa93b8ba.1477327674.git.panand@redhat.com>
Message-ID: <0910DD04CBD6DE4193FCF86B9C00BE9701E7A30E@BPXM01GP.gisp.nec.co.jp>

Hello Pratysh,

>Currently we translate some of the VA areas using linear mapping while some
>other(which can not be linearly mapped) using page table.
>
>However, we will have entry of a page in the page table irrespective of its
>virtual region. So, we can always look into page table for any VA to PA
>translation. This approach will solve lot of complexity in makedumpfile. It
>will in turn remove dependency over variables like VMALLOC_START,
>MODULES_VADDR etc whose definition keeps changing in newer kernel version.
>
>Moreover, I do not see any side effect of this approach in terms of
>execution timing. I tested with IBM x3950 X6 machine having 4136359 MB of
>memory. These are the results of makedumpfile execution time:
>
>Without this patch:
>===================
>With -d 31:
>Trial 1: 237.59526248 S
>Trial 2: 235.236914962 S
>Trail 3: 237.678712045 S
>
>With -d 1:
>Trial 1: 2548.905296877 S
>Trial 2: 2549.759881756 S
>
>With this patch:
>===================
>With -d 31:
>Trial 1: 232.713841516 S
>Trial 2: 228.45697177 S
>Trail 3: 232.942262441 S
>
>With -d 1:
>Trial 1: 2768.424565806 S
>Trial 2: 2749.622115455 S
>Trail 3: 2537.770359073 S

Could you increase the number of trials ?
If the average time is close to the results of Trial 1 (2768s) and 2 (2749s),
the regression rate is 8% and it sounds neither large nor small.
If the average is a level of 2500s like Trial 3, it's ideal.

>Signed-off-by: Pratyush Anand <panand at redhat.com>
>---
> arch/x86_64.c  | 42 ++++++++----------------------------------
> makedumpfile.h |  4 ++--
> 2 files changed, 10 insertions(+), 36 deletions(-)
>
>diff --git a/arch/x86_64.c b/arch/x86_64.c
>index a96fd8ae00a1..fe2764a8bec2 100644
>--- a/arch/x86_64.c
>+++ b/arch/x86_64.c
>@@ -203,6 +203,12 @@ vtop4_x86_64(unsigned long vaddr)
> {
> 	unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
> 	unsigned long pte_paddr, pte;
>+	unsigned long phys_base;
>+
>+	if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
>+		phys_base = info->phys_base;
>+	else
>+		phys_base = 0;
>
> 	if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
> 		ERRMSG("Can't get the symbol of init_level4_pgt.\n");
>@@ -212,9 +218,9 @@ vtop4_x86_64(unsigned long vaddr)
> 	/*
> 	 * Get PGD.
> 	 */
>-	page_dir  = SYMBOL(init_level4_pgt);
>+	page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + phys_base;

I want to confirm that this VA to PA translation is always safe,
otherwise we should do the condition check which was done in
vaddr_to_paddr_x86_64(), isn't it ?


Thanks,
Atsushi Kumagai

> 	page_dir += pml4_index(vaddr) * sizeof(unsigned long);
>-	if (!readmem(VADDR, page_dir, &pml4, sizeof pml4)) {
>+	if (!readmem(PADDR, page_dir, &pml4, sizeof pml4)) {
> 		ERRMSG("Can't get pml4 (page_dir:%lx).\n", page_dir);
> 		return NOT_PADDR;
> 	}
>@@ -285,38 +291,6 @@ vtop4_x86_64(unsigned long vaddr)
> 	return (pte & ENTRY_MASK) + PAGEOFFSET(vaddr);
> }
>
>-unsigned long long
>-vaddr_to_paddr_x86_64(unsigned long vaddr)
>-{
>-	unsigned long phys_base;
>-	unsigned long long paddr;
>-
>-	/*
>-	 * Check the relocatable kernel.
>-	 */
>-	if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
>-		phys_base = info->phys_base;
>-	else
>-		phys_base = 0;
>-
>-	if (is_vmalloc_addr_x86_64(vaddr)) {
>-		if ((paddr = vtop4_x86_64(vaddr)) == NOT_PADDR) {
>-			ERRMSG("Can't convert a virtual address(%lx) to " \
>-			    "physical address.\n", vaddr);
>-			return NOT_PADDR;
>-		}
>-	} else if (vaddr >= __START_KERNEL_map) {
>-		paddr = vaddr - __START_KERNEL_map + phys_base;
>-
>-	} else {
>-		if (is_xen_memory())
>-			paddr = vaddr - PAGE_OFFSET_XEN_DOM0;
>-		else
>-			paddr = vaddr - PAGE_OFFSET;
>-	}
>-	return paddr;
>-}
>-
> /*
>  * for Xen extraction
>  */
>diff --git a/makedumpfile.h b/makedumpfile.h
>index a5955ff750e5..13559651feb6 100644
>--- a/makedumpfile.h
>+++ b/makedumpfile.h
>@@ -863,12 +863,12 @@ int is_vmalloc_addr_x86_64(ulong vaddr);
> int get_phys_base_x86_64(void);
> int get_machdep_info_x86_64(void);
> int get_versiondep_info_x86_64(void);
>-unsigned long long vaddr_to_paddr_x86_64(unsigned long vaddr);
>+unsigned long long vtop4_x86_64(unsigned long vaddr);
> #define find_vmemmap()		find_vmemmap_x86_64()
> #define get_phys_base()		get_phys_base_x86_64()
> #define get_machdep_info()	get_machdep_info_x86_64()
> #define get_versiondep_info()	get_versiondep_info_x86_64()
>-#define vaddr_to_paddr(X)	vaddr_to_paddr_x86_64(X)
>+#define vaddr_to_paddr(X)	vtop4_x86_64(X)
> #define is_phys_addr(X)		(!is_vmalloc_addr_x86_64(X))
> #endif /* x86_64 */
>
>--
>2.7.4
>
>
>_______________________________________________
>kexec mailing list
>kexec at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/kexec


From ats-kumagai at wm.jp.nec.com  Tue Oct 25 02:19:40 2016
From: ats-kumagai at wm.jp.nec.com (Atsushi Kumagai)
Date: Tue, 25 Oct 2016 09:19:40 +0000
Subject: makedumpfile issues many readpage_elf: Attempt to read
 non-existent page
In-Reply-To: <161d0e6f-5b1c-dfa9-aa28-5393e2a86d1d@canonical.com>
References: <57E3DCDB.5020308@canonical.com>
 <0910DD04CBD6DE4193FCF86B9C00BE9701E6B42E@BPXM01GP.gisp.nec.co.jp>
 <57ED187D.3040007@canonical.com>
 <CAL0thcP2Pp43nWLJ_jfwDQnW4RNRpP27fpymQ8pPtORPaeX8nQ@mail.gmail.com>
 <161d0e6f-5b1c-dfa9-aa28-5393e2a86d1d@canonical.com>
Message-ID: <0910DD04CBD6DE4193FCF86B9C00BE9701E7A2F3@BPXM01GP.gisp.nec.co.jp>

Hello,

>> I have now completed the kernel bisection between 4.7.8 and 4.8-rc1 and
>> identified the kernel modification that triggers the errors cited above :
>>
>>> commit 021182e52fe01c1f7b126f97fd6ba048dc4234fd
>>> Author: Thomas Garnier <thgarnie at google.com>
>>> Date:   Tue Jun 21 17:47:03 2016 -0700
>>>
>>>     x86/mm: Enable KASLR for physical mapping memory regions
>>>
>>>     Add the physical mapping in the list of randomized memory regions.
>>>
>>>     The physical memory mapping holds most allocations from boot and heap
>>>     allocators. Knowing the base address and physical memory size, an attacker
>>>     can deduce the PDE virtual address for the vDSO memory page. This attack
>>>     was demonstrated at CanSecWest 2016, in the following presentation:
>>>
>>>       "Getting Physical: Extreme Abuse of Intel Based Paged Systems":
>>>
>https://github.com/n3k/CansecWest2016_Getting_Physical_Extreme_Abuse_of_Intel_Based_Paging_Systems/blob/master/Prese
>ntation/CanSec2016_Presentation.pdf
>>>
>>>     (See second part of the presentation).
>>>
>>>     The exploits used against Linux worked successfully against 4.6+ but
>>>     fail with KASLR memory enabled:
>>>
>>>
>https://github.com/n3k/CansecWest2016_Getting_Physical_Extreme_Abuse_of_Intel_Based_Paging_Systems/tree/master/Demos
>/Linux/exploits
>>>
>>>     Similar research was done at Google leading to this patch proposal.
>>>
>>>     Variants exists to overwrite /proc or /sys objects ACLs leading to
>>>     elevation of privileges. These variants were tested against 4.6+.
>>>
>>>     The page offset used by the compressed kernel retains the static value
>>>     since it is not yet randomized during this boot stage.
>>>
>>>     Signed-off-by: Thomas Garnier <thgarnie at google.com>
>>>     Signed-off-by: Kees Cook <keescook at chromium.org>
>>>     Cc: Alexander Kuleshov <kuleshovmail at gmail.com>
>> <truncated>
>>
>> The interesting change seems to be :
>>
>>> -#define __PAGE_OFFSET           _AC(0xffff880000000000, UL)
>>> +#define __PAGE_OFFSET_BASE      _AC(0xffff880000000000, UL)
>>> +#ifdef CONFIG_RANDOMIZE_MEMORY
>>> +#define __PAGE_OFFSET           page_offset_base
>>> +#else
>>> +#define __PAGE_OFFSET           __PAGE_OFFSET_BASE
>>> +#endif /* CONFIG_RANDOMIZE_MEMORY */
>>
>> I'll try to see if I can fix that.
>>
>> Kind regards,
>>
>> ...Louis
>>
>>
>>
>>
>
>Some more *important* information in this mostly monologue thread : Pratyush
>Anand has pushed a patch to the list earlier today that apparently fixes this
>issue :
>
>[PATCH Makedumpfile 1/4] x86_64: Calculate page_offset from pt_load[1]
>
>HTH,
>
>Kind regards,

Yeah, It appears so. I'm reviewing the patches,
please wait for that.
I appreciate your investigation for this issue.


Thanks,
Atsushi Kumagai

>...Louis
>
>[1] https://www.mail-archive.com/kexec at lists.infradead.org/msg16628.html
>--
>Louis Bouchard
>Software engineer, Cloud & Sustaining eng.
>Canonical Ltd
>Ubuntu developer                       Debian Maintainer
>GPG : 429D 7A3B DD05 B6F8 AF63  B9C4 8B3D 867C 823E 7A61

From panand at redhat.com  Tue Oct 25 03:34:50 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 16:04:50 +0530
Subject: [PATCH Makedumpfile 00/10] arm64 cleanup and kaslr support
In-Reply-To: <cover.1477378297.git.panand@redhat.com>
References: <cover.1477378297.git.panand@redhat.com>
Message-ID: <ebbc4d83-2b62-80a0-b729-20e04b230d47@redhat.com>

Hi Sameer,

Although you had already tested my tree on your platform in past. 
However, it would be nice if you can test these posted versions of 
patches just for sanity and provide your tested-by.

~Pratyush

On Tuesday 25 October 2016 12:52 PM, Pratyush Anand wrote:
> These patches were lying in my tree for quite some time now. VMCOREINFO
> numbers/symbols used in these patches have been made part of kdump kernel
> patches for last few versions including v26. So, there seems no contention
> on embedding VA_BITS, kimage_voffset and PHYS_OFFSET into vmcore.
>
> These patches cleans up a lot arm64 code and also immunize it with many
> kernel changes. Additionally,it adds 4 level 4K page support and support for
> KASLR enabled kernel.
>
> Azriel Samson (1):
>   arm64: Add support for 4level 4K page translations table
>
> Pratyush Anand (9):
>   arm64: cleanup code, comment, blank space, blank lines etc
>   read_vmcoreinfo_long: Allow to read hex values as well
>   Introduce read_vmcoreinfo_ulong()
>   arm64: use already available PAGESIZE() and PAGESHIFT() macros
>   arm64: fix page_offset definition
>   arm64: fix re-filtering
>   arm64: use value of VA_BITS and PHYS_OFFSET embedded into vmcore
>   arm64: immunize identity mapped address finding w.r.t. kernel changes
>   arm64: fix memory layout as per changes in v4.6 kernel
>
>  arch/arm64.c   | 245 ++++++++++++++++++++++-----------------------------------
>  makedumpfile.c |  46 +++++++++++
>  makedumpfile.h |  28 +++++--
>  3 files changed, 162 insertions(+), 157 deletions(-)
>


From smith.not.western at gmail.com  Tue Oct 25 04:59:49 2016
From: smith.not.western at gmail.com (Simon T)
Date: Tue, 25 Oct 2016 12:59:49 +0100
Subject: kexec and arm64 advice
In-Reply-To: <16c384ed-0875-daa8-b52a-f03af764460b@codeaurora.org>
References: <CAKYm0coteEEapCNwmj+KmGd57C_C3--nXQfjyD_FLoGXSkqMkQ@mail.gmail.com>
 <16c384ed-0875-daa8-b52a-f03af764460b@codeaurora.org>
Message-ID: <CAKYm0coPOhCWQ=yKs6WCzMs=nZ3eTq3V_8Y52CLRc3OmUbHLeQ@mail.gmail.com>

Hi Sameer,

The running kernel and the kernel I am trying to kexec into are the
same -- for testing purposes I'm just trying to kexec into a second
copy of the same kernel I'm running. The .config file has kexec
defined:

$ grep -i kexec .config
CONFIG_KERNEL_KEXEC=y
CONFIG_PACKAGE_kexec-tools=y
CONFIG_KEXEC_TOOLS_TARGET_NAME="aarch64"
# CONFIG_KEXEC_TOOLS_kdump is not set
CONFIG_KEXEC_ZLIB=y
# CONFIG_KEXEC_LZMA is not set

Is there another way to verify if the kernel actually built with the
kexec_load syscall or not?

Thanks,

Simon

On Mon, Oct 24, 2016 at 11:53 PM, Goel, Sameer <sgoel at codeaurora.org> wrote:
> It seems that the kexec_load syscall is not defined. Can you please check
> the configs of your running kernel once again?
>
> Thanks,
> Sameer
>
>
> On 10/24/2016 8:42 AM, Simon T wrote:
>>
>> Hi,
>>
>> I'm trying to get kexec working on a cross-compiled arm64/aarch64
>> system, using Linux kernel 4.4.23. I'm using kexec-tool's master
>> branch (commit e345e27417db00a9e754ca0ca14b2ec87d0552f7 from
>> https://git.kernel.org/cgit/linux/kernel/git/geoff/kexec-tools.git). I
>> initially tried using the patches for linux-kexec's kexec-13 branch
>> with manual massaging in some spots because kexec-13 is for 4.4.0 not
>> 4.4.23. Both tools and kernel appear to build fine, however when it
>> comes time to kexec, I encounter this message: "kexec_load failed:
>> Function not implemented"
>>
>> Searching through the patches, I don't find any reference to kexec_load
>> itself.
>>
>> Should I be applying a different version of kexec-tools, or
>> linux-kexec patches, to my build? (I'm restricted to 4.4.23 as the
>> base kernel)
>>
>> Is there a way post compile to check if the kexec_load function is
>> implemented, aside from actually deploying the image and calling
>> kexec? I've run strings against the Image but it doesn't give an exact
>> match for kexec_load (see below).
>>
>> Anything else I should be looking at?
>>
>> # kexec -l /mnt/target/boot/vmlinux --initrd=/tmp/root.sfs
>> Modified cmdline:root=/dev/mmcblk0p2
>> Unable to find /proc/device-tree/chosen/[linux,]stdout-path, printing
>> from purgatory is disabled
>> kexec_load failed: Function not implemented
>> entry       = 0x8095f000 flags = 0xb70000
>> nr_segments = 4
>> segment[0].buf   = 0x7fa0f64010
>> segment[0].bufsz = 0x7fbc00
>> segment[0].mem   = 0x80080000
>> segment[0].memsz = 0x8d0000
>> segment[1].buf   = 0x20cc0830
>> segment[1].bufsz = 0xe515
>> segment[1].mem   = 0x80950000
>> segment[1].memsz = 0xf000
>> segment[2].buf   = 0x20ccf840
>> segment[2].bufsz = 0x6080
>> segment[2].mem   = 0x8095f000
>> segment[2].memsz = 0x7000
>> segment[3].buf   = 0x7f9e843010
>> segment[3].bufsz = 0x2720000
>> segment[3].mem   = 0xc0000000
>> segment[3].memsz = 0x2720000
>>
>> (I've also tried kexec -l with boot/Image instead of boot/vmlinux)
>>
>> $ grep -i kexec .config
>> CONFIG_KERNEL_KEXEC=y
>> CONFIG_PACKAGE_kexec-tools=y
>> CONFIG_KEXEC_TOOLS_TARGET_NAME="aarch64"
>> # CONFIG_KEXEC_TOOLS_kdump is not set
>> CONFIG_KEXEC_ZLIB=y
>> # CONFIG_KEXEC_LZMA is not set
>>
>> $ strings <build_dir>/arch/arm64/boot/Image  | grep kexec_load
>> Wcompat_sys_kexec_load
>> Wsys_kexec_load
>>
>> Thanks!
>>
>> Simon
>>
>> _______________________________________________
>> kexec mailing list
>> kexec at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/kexec
>>
>
> --
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project.


From panand at redhat.com  Tue Oct 25 08:12:02 2016
From: panand at redhat.com (Pratyush Anand)
Date: Tue, 25 Oct 2016 20:42:02 +0530
Subject: [PATCH Makedumpfile 2/4] x86_64: translate all VA to PA using
 page table values
In-Reply-To: <0910DD04CBD6DE4193FCF86B9C00BE9701E7A30E@BPXM01GP.gisp.nec.co.jp>
References: <cover.1477327674.git.panand@redhat.com>
 <b54b1e73bc4302fa7222c44a9cf46d57aa93b8ba.1477327674.git.panand@redhat.com>
 <0910DD04CBD6DE4193FCF86B9C00BE9701E7A30E@BPXM01GP.gisp.nec.co.jp>
Message-ID: <f29a272d-8b82-d0d7-a2f2-c4af6474fff6@redhat.com>

Hi Atsushi,

Thanks for the review.

On Tuesday 25 October 2016 02:50 PM, Atsushi Kumagai wrote:
> Hello Pratysh,
>
>> Currently we translate some of the VA areas using linear mapping while some
>> other(which can not be linearly mapped) using page table.
>>
>> However, we will have entry of a page in the page table irrespective of its
>> virtual region. So, we can always look into page table for any VA to PA
>> translation. This approach will solve lot of complexity in makedumpfile. It
>> will in turn remove dependency over variables like VMALLOC_START,
>> MODULES_VADDR etc whose definition keeps changing in newer kernel version.
>>
>> Moreover, I do not see any side effect of this approach in terms of
>> execution timing. I tested with IBM x3950 X6 machine having 4136359 MB of
>> memory. These are the results of makedumpfile execution time:
>>
>> Without this patch:
>> ===================
>> With -d 31:
>> Trial 1: 237.59526248 S
>> Trial 2: 235.236914962 S
>> Trail 3: 237.678712045 S
>>
>> With -d 1:
>> Trial 1: 2548.905296877 S
>> Trial 2: 2549.759881756 S
>>
>> With this patch:
>> ===================
>> With -d 31:
>> Trial 1: 232.713841516 S
>> Trial 2: 228.45697177 S
>> Trail 3: 232.942262441 S
>>
>> With -d 1:
>> Trial 1: 2768.424565806 S
>> Trial 2: 2749.622115455 S
>> Trail 3: 2537.770359073 S
>
> Could you increase the number of trials ?

OK, I can do that. Might take some time, as I will have to arrange that  
high memory machine again.

> If the average time is close to the results of Trial 1 (2768s) and 2 (2749s),
> the regression rate is 8% and it sounds neither large nor small.
> If the average is a level of 2500s like Trial 3, it's ideal.
>
>> Signed-off-by: Pratyush Anand <panand at redhat.com>
>> ---
>> arch/x86_64.c  | 42 ++++++++----------------------------------
>> makedumpfile.h |  4 ++--
>> 2 files changed, 10 insertions(+), 36 deletions(-)
>>
>> diff --git a/arch/x86_64.c b/arch/x86_64.c
>> index a96fd8ae00a1..fe2764a8bec2 100644
>> --- a/arch/x86_64.c
>> +++ b/arch/x86_64.c
>> @@ -203,6 +203,12 @@ vtop4_x86_64(unsigned long vaddr)
>> {
>> 	unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
>> 	unsigned long pte_paddr, pte;
>> +	unsigned long phys_base;
>> +
>> +	if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
>> +		phys_base = info->phys_base;
>> +	else
>> +		phys_base = 0;
>>
>> 	if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
>> 		ERRMSG("Can't get the symbol of init_level4_pgt.\n");
>> @@ -212,9 +218,9 @@ vtop4_x86_64(unsigned long vaddr)
>> 	/*
>> 	 * Get PGD.
>> 	 */
>> -	page_dir  = SYMBOL(init_level4_pgt);
>> +	page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + phys_base;
>
> I want to confirm that this VA to PA translation is always safe,
> otherwise we should do the condition check which was done in
> vaddr_to_paddr_x86_64(), isn't it ?
>

I think this should be safe, however x86 expert can comment better.  
Baoquan any comment here?

~Pratyush
>
> Thanks,
> Atsushi Kumagai
>
>> 	page_dir += pml4_index(vaddr) * sizeof(unsigned long);
>> -	if (!readmem(VADDR, page_dir, &pml4, sizeof pml4)) {
>> +	if (!readmem(PADDR, page_dir, &pml4, sizeof pml4)) {
>> 		ERRMSG("Can't get pml4 (page_dir:%lx).\n", page_dir);
>> 		return NOT_PADDR;
>> 	}
>> @@ -285,38 +291,6 @@ vtop4_x86_64(unsigned long vaddr)
>> 	return (pte & ENTRY_MASK) + PAGEOFFSET(vaddr);
>> }
>>
>> -unsigned long long
>> -vaddr_to_paddr_x86_64(unsigned long vaddr)
>> -{
>> -	unsigned long phys_base;
>> -	unsigned long long paddr;
>> -
>> -	/*
>> -	 * Check the relocatable kernel.
>> -	 */
>> -	if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
>> -		phys_base = info->phys_base;
>> -	else
>> -		phys_base = 0;
>> -
>> -	if (is_vmalloc_addr_x86_64(vaddr)) {
>> -		if ((paddr = vtop4_x86_64(vaddr)) == NOT_PADDR) {
>> -			ERRMSG("Can't convert a virtual address(%lx) to " \
>> -			    "physical address.\n", vaddr);
>> -			return NOT_PADDR;
>> -		}
>> -	} else if (vaddr >= __START_KERNEL_map) {
>> -		paddr = vaddr - __START_KERNEL_map + phys_base;
>> -
>> -	} else {
>> -		if (is_xen_memory())
>> -			paddr = vaddr - PAGE_OFFSET_XEN_DOM0;
>> -		else
>> -			paddr = vaddr - PAGE_OFFSET;
>> -	}
>> -	return paddr;
>> -}
>> -
>> /*
>>  * for Xen extraction
>>  */
>> diff --git a/makedumpfile.h b/makedumpfile.h
>> index a5955ff750e5..13559651feb6 100644
>> --- a/makedumpfile.h
>> +++ b/makedumpfile.h
>> @@ -863,12 +863,12 @@ int is_vmalloc_addr_x86_64(ulong vaddr);
>> int get_phys_base_x86_64(void);
>> int get_machdep_info_x86_64(void);
>> int get_versiondep_info_x86_64(void);
>> -unsigned long long vaddr_to_paddr_x86_64(unsigned long vaddr);
>> +unsigned long long vtop4_x86_64(unsigned long vaddr);
>> #define find_vmemmap()		find_vmemmap_x86_64()
>> #define get_phys_base()		get_phys_base_x86_64()
>> #define get_machdep_info()	get_machdep_info_x86_64()
>> #define get_versiondep_info()	get_versiondep_info_x86_64()
>> -#define vaddr_to_paddr(X)	vaddr_to_paddr_x86_64(X)
>> +#define vaddr_to_paddr(X)	vtop4_x86_64(X)
>> #define is_phys_addr(X)		(!is_vmalloc_addr_x86_64(X))
>> #endif /* x86_64 */
>>
>> --
>> 2.7.4
>>
>>
>> _______________________________________________
>> kexec mailing list
>> kexec at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/kexec


From geoff at infradead.org  Tue Oct 25 09:57:29 2016
From: geoff at infradead.org (Geoff Levand)
Date: Tue, 25 Oct 2016 09:57:29 -0700
Subject: kexec and arm64 advice
In-Reply-To: <CAKYm0coteEEapCNwmj+KmGd57C_C3--nXQfjyD_FLoGXSkqMkQ@mail.gmail.com>
References: <CAKYm0coteEEapCNwmj+KmGd57C_C3--nXQfjyD_FLoGXSkqMkQ@mail.gmail.com>
Message-ID: <3118d747-8f11-fae5-9541-0fb0917eaa14@infradead.org>

On 10/24/2016 07:42 AM, Simon T wrote:
> Both tools and kernel appear to build fine, however when it
> comes time to kexec, I encounter this message: "kexec_load failed:
> Function not implemented"

It seems your kernel needs kexec support. Try something like:

  cat /proc/config.gz | gunzip | egrep 'KEXEC'

-Geoff


From prarit at redhat.com  Tue Oct 25 11:32:16 2016
From: prarit at redhat.com (Prarit Bhargava)
Date: Tue, 25 Oct 2016 14:32:16 -0400
Subject: [PATCH] arch/x86: Don't try to poke disabled/non-existent APIC
In-Reply-To: <1477102684-5092-1-git-send-email-ville.syrjala@linux.intel.com>
References: <1477102684-5092-1-git-send-email-ville.syrjala@linux.intel.com>
Message-ID: <580FA530.6040905@redhat.com>



On 10/21/2016 10:18 PM, ville.syrjala at linux.intel.com wrote:
> From: Ville Syrj?l? <ville.syrjala at linux.intel.com>
> 
> Apparently trying to poke a disabled or non-existent APIC
> leads to a box that doesn't even boot. Let's not do that.
> 
> No real clue if this is the right fix, but at least my
> P3 machine boots again.
> 
> Cc: stable at vger.kernel.org
> Cc: Ingo Molnar <mingo at redhat.com>
> Cc: "H. Peter Anvin" <hpa at zytor.com>
> Cc: x86 at kernel.org
> Cc: Prarit Bhargava <prarit at redhat.com>
> Cc: Peter Zijlstra <peterz at infradead.org>
> Cc: Len Brown <len.brown at intel.com>
> Cc: Borislav Petkov <bp at suse.de>
> Cc: Andi Kleen <ak at linux.intel.com>
> Cc: Jiri Olsa <jolsa at redhat.com>
> Cc: Juergen Gross <jgross at suse.com>
> Cc: dyoung at redhat.com
> Cc: Eric Biederman <ebiederm at xmission.com>
> Cc: kexec at lists.infradead.org
> Cc: Thomas Gleixner <tglx at linutronix.de>
> Fixes: 2a51fe083eba ("arch/x86: Handle non enumerated CPU after physical hotplug")
> Signed-off-by: Ville Syrj?l? <ville.syrjala at linux.intel.com>
> ---
>  arch/x86/kernel/smpboot.c | 16 +++++++++-------
>  1 file changed, 9 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
> index 951f093a96fe..42f5eb7b4f6c 100644
> --- a/arch/x86/kernel/smpboot.c
> +++ b/arch/x86/kernel/smpboot.c
> @@ -1409,15 +1409,17 @@ __init void prefill_possible_map(void)
>  
>  	/* No boot processor was found in mptable or ACPI MADT */
>  	if (!num_processors) {
> -		int apicid = boot_cpu_physical_apicid;
> -		int cpu = hard_smp_processor_id();
> +		if (boot_cpu_has(X86_FEATURE_APIC)) {


It looks okay to gate on X86_FEATURE_APIC, but not sure if it should be

     cpu_has(&cpu_data(0), X86_FEATURE_APIC)

since smp_store_boot_cpu_info() was already called.

tglx?

P.




> +			int apicid = boot_cpu_physical_apicid;
> +			int cpu = hard_smp_processor_id();
>  
> -		pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu);
> +			pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu);
>  
> -		/* Make sure boot cpu is enumerated */
> -		if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
> -		    apic->apic_id_valid(apicid))
> -			generic_processor_info(apicid, boot_cpu_apic_version);
> +			/* Make sure boot cpu is enumerated */
> +			if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
> +			    apic->apic_id_valid(apicid))
> +				generic_processor_info(apicid, boot_cpu_apic_version);
> +		}
>  
>  		if (!num_processors)
>  			num_processors = 1;
> 


From bhe at redhat.com  Tue Oct 25 16:28:04 2016
From: bhe at redhat.com (bhe at redhat.com)
Date: Wed, 26 Oct 2016 07:28:04 +0800
Subject: [PATCH Makedumpfile 2/4] x86_64: translate all VA to PA using
 page table values
In-Reply-To: <f29a272d-8b82-d0d7-a2f2-c4af6474fff6@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <b54b1e73bc4302fa7222c44a9cf46d57aa93b8ba.1477327674.git.panand@redhat.com>
 <0910DD04CBD6DE4193FCF86B9C00BE9701E7A30E@BPXM01GP.gisp.nec.co.jp>
 <f29a272d-8b82-d0d7-a2f2-c4af6474fff6@redhat.com>
Message-ID: <20161025232804.GB2975@x1>

On 10/25/16 at 08:42pm, Pratyush Anand wrote:
> > > With -d 1:
> > > Trial 1: 2768.424565806 S
> > > Trial 2: 2749.622115455 S
> > > Trail 3: 2537.770359073 S
> > 
> > Could you increase the number of trials ?
> 
> OK, I can do that. Might take some time, as I will have to arrange that high
> memory machine again.
> 
> > If the average time is close to the results of Trial 1 (2768s) and 2 (2749s),
> > the regression rate is 8% and it sounds neither large nor small.
> > If the average is a level of 2500s like Trial 3, it's ideal.
> > 
> > > Signed-off-by: Pratyush Anand <panand at redhat.com>
> > > ---
> > > arch/x86_64.c  | 42 ++++++++----------------------------------
> > > makedumpfile.h |  4 ++--
> > > 2 files changed, 10 insertions(+), 36 deletions(-)
> > > 
> > > diff --git a/arch/x86_64.c b/arch/x86_64.c
> > > index a96fd8ae00a1..fe2764a8bec2 100644
> > > --- a/arch/x86_64.c
> > > +++ b/arch/x86_64.c
> > > @@ -203,6 +203,12 @@ vtop4_x86_64(unsigned long vaddr)
> > > {
> > > 	unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
> > > 	unsigned long pte_paddr, pte;
> > > +	unsigned long phys_base;
> > > +
> > > +	if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
> > > +		phys_base = info->phys_base;
> > > +	else
> > > +		phys_base = 0;
> > > 
> > > 	if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
> > > 		ERRMSG("Can't get the symbol of init_level4_pgt.\n");
> > > @@ -212,9 +218,9 @@ vtop4_x86_64(unsigned long vaddr)
> > > 	/*
> > > 	 * Get PGD.
> > > 	 */
> > > -	page_dir  = SYMBOL(init_level4_pgt);
> > > +	page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + phys_base;
> > 
> > I want to confirm that this VA to PA translation is always safe,
> > otherwise we should do the condition check which was done in
> > vaddr_to_paddr_x86_64(), isn't it ?
> > 
> 
> I think this should be safe, however x86 expert can comment better. Baoquan
> any comment here?

Yes, I think this is safe. Below is the physical to virtual address
translation function in x86 64. And init_level4_pgt is a global variable
located in kernel text region. 

arch/x86/include/asm/page_64.h

static inline unsigned long __phys_addr_nodebug(unsigned long x)
{
        unsigned long y = x - __START_KERNEL_map;
 
        /* use the carry flag to determine if x was < __START_KERNEL_map */
        x = y + ((x > y) ? phys_base : (__START_KERNEL_map - PAGE_OFFSET));
 
        return x;
}



From panand at redhat.com  Tue Oct 25 21:37:23 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 26 Oct 2016 10:07:23 +0530
Subject: [PATCH v2] arm64: Add support for additional relocations in the
 kexec purgatory code
In-Reply-To: <1476960211-25594-1-git-send-email-catalin.marinas@arm.com>
References: <1476960211-25594-1-git-send-email-catalin.marinas@arm.com>
Message-ID: <6eb25c47-6fbd-4b7a-e450-6de6388a9d55@redhat.com>



On Thursday 20 October 2016 04:13 PM, Catalin Marinas wrote:
> When compiling the kexec-tools with gcc6, the following additional
> reolcations are generated in the purgatory.ro file:
>
> R_AARCH64_ADR_PREL_PG_HI21
> R_AARCH64_ADD_ABS_LO12_NC
> R_AARCH64_LDST64_ABS_LO12_NC
>
> This patch modifies the arm64 machine_apply_elf_rel() function to handle
> these relocations.

Noticed that, gcc version of fedora koji(6.2.1-2.fc25) inserts another 
relocation and kexec-tools generates following error.

machine_apply_elf_rel: ERROR Unknown type: 261

I have a fixup here:
https://github.com/pratyushanand/kexec-tools/commit/0eb8a908f617e0f957df7fb3ef293596f47e6832

May be I will send them separately.

~Pratyush
>
> Cc: Geoff Levand <geoff at infradead.org>
> Signed-off-by: Catalin Marinas <catalin.marinas at arm.com>
> ---
>
> Changes for v2:
> - Fixed the type string to drop the "R_AARCH64_" prefix
>
>  kexec/arch/arm64/kexec-arm64.c | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>
> diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
> index 2e8839a..e067a23 100644
> --- a/kexec/arch/arm64/kexec-arm64.c
> +++ b/kexec/arch/arm64/kexec-arm64.c
> @@ -550,6 +550,14 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
>  # define R_AARCH64_ADR_PREL_LO21 274
>  #endif
>
> +#if !defined(R_AARCH64_ADR_PREL_PG_HI21)
> +# define R_AARCH64_ADR_PREL_PG_HI21 275
> +#endif
> +
> +#if !defined(R_AARCH64_ADD_ABS_LO12_NC)
> +# define R_AARCH64_ADD_ABS_LO12_NC 277
> +#endif
> +
>  #if !defined(R_AARCH64_JUMP26)
>  # define R_AARCH64_JUMP26 282
>  #endif
> @@ -558,10 +566,15 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
>  # define R_AARCH64_CALL26 283
>  #endif
>
> +#if !defined(R_AARCH64_LDST64_ABS_LO12_NC)
> +# define R_AARCH64_LDST64_ABS_LO12_NC 286
> +#endif
> +
>  	uint64_t *loc64;
>  	uint32_t *loc32;
>  	uint64_t *location = (uint64_t *)ptr;
>  	uint64_t data = *location;
> +	uint64_t imm;
>  	const char *type = NULL;
>
>  	switch(r_type) {
> @@ -585,6 +598,19 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
>  		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
>  			+ (((value - address) << 3) & 0xffffe0));
>  		break;
> +	case R_AARCH64_ADR_PREL_PG_HI21:
> +		type = "ADR_PREL_PG_HI21";
> +		imm = ((value & ~0xfff) - (address & ~0xfff)) >> 12;
> +		loc32 = ptr;
> +		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
> +			+ ((imm & 3) << 29) + ((imm & 0x1ffffc) << (5 - 2)));
> +		break;
> +	case R_AARCH64_ADD_ABS_LO12_NC:
> +		type = "ADD_ABS_LO12_NC";
> +		loc32 = ptr;
> +		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
> +			+ ((value & 0xfff) << 10));
> +		break;
>  	case R_AARCH64_JUMP26:
>  		type = "JUMP26";
>  		loc32 = ptr;
> @@ -597,6 +623,15 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
>  		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
>  			+ (((value - address) >> 2) & 0x3ffffff));
>  		break;
> +	case R_AARCH64_LDST64_ABS_LO12_NC:
> +		if (value & 7)
> +			die("%s: ERROR Unaligned value: %lx\n", __func__,
> +				value);
> +		type = "LDST64_ABS_LO12_NC";
> +		loc32 = ptr;
> +		*loc32 = cpu_to_le32(le32_to_cpu(*loc32)
> +			+ ((value & 0xff8) << (10 - 3)));
> +		break;
>  	default:
>  		die("%s: ERROR Unknown type: %lu\n", __func__, r_type);
>  		break;
>


From panand at redhat.com  Tue Oct 25 21:40:23 2016
From: panand at redhat.com (Pratyush Anand)
Date: Wed, 26 Oct 2016 10:10:23 +0530
Subject: [PATCH] arm64: Add support of R_AARCH64_PREL32 relocation in purgatory
Message-ID: <0eb8a908f617e0f957df7fb3ef293596f47e6832.1477456661.git.panand@redhat.com>

gcc version in fedora koji is  6.2.1-2.fc25. kexec-tools compiled with this
gcc produced another relocation error:

machine_apply_elf_rel: ERROR Unknown type: 261

This patch fixes the above error.

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 kexec/arch/arm64/kexec-arm64.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 218f0bc832cd..b12de4772412 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -720,6 +720,10 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 # define R_AARCH64_ABS64 257
 #endif
 
+#if !defined(R_AARCH64_PREL32)
+# define R_AARCH64_PREL32 261
+#endif
+
 #if !defined(R_AARCH64_LD_PREL_LO19)
 # define R_AARCH64_LD_PREL_LO19 273
 #endif
@@ -761,6 +765,11 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 		loc64 = ptr;
 		*loc64 = cpu_to_elf64(ehdr, elf64_to_cpu(ehdr, *loc64) + value);
 		break;
+	case R_AARCH64_PREL32:
+		type = "PREL32";
+		loc32 = ptr;
+		*loc32 = cpu_to_elf32(ehdr, elf32_to_cpu(ehdr, *loc32) + value - address);
+		break;
 	case R_AARCH64_LD_PREL_LO19:
 		type = "LD_PREL_LO19";
 		loc32 = ptr;
-- 
2.7.4



From ats-kumagai at wm.jp.nec.com  Tue Oct 25 23:24:43 2016
From: ats-kumagai at wm.jp.nec.com (Atsushi Kumagai)
Date: Wed, 26 Oct 2016 06:24:43 +0000
Subject: [PATCH Makedumpfile 2/4] x86_64: translate all VA to PA using
 page table values
In-Reply-To: <20161025232804.GB2975@x1>
References: <cover.1477327674.git.panand@redhat.com>
 <b54b1e73bc4302fa7222c44a9cf46d57aa93b8ba.1477327674.git.panand@redhat.com>
 <0910DD04CBD6DE4193FCF86B9C00BE9701E7A30E@BPXM01GP.gisp.nec.co.jp>
 <f29a272d-8b82-d0d7-a2f2-c4af6474fff6@redhat.com> <20161025232804.GB2975@x1>
Message-ID: <0910DD04CBD6DE4193FCF86B9C00BE9701E7A7B6@BPXM01GP.gisp.nec.co.jp>

>On 10/25/16 at 08:42pm, Pratyush Anand wrote:
>> > > With -d 1:
>> > > Trial 1: 2768.424565806 S
>> > > Trial 2: 2749.622115455 S
>> > > Trail 3: 2537.770359073 S
>> >
>> > Could you increase the number of trials ?
>>
>> OK, I can do that. Might take some time, as I will have to arrange that high
>> memory machine again.
>>
>> > If the average time is close to the results of Trial 1 (2768s) and 2 (2749s),
>> > the regression rate is 8% and it sounds neither large nor small.
>> > If the average is a level of 2500s like Trial 3, it's ideal.
>> >
>> > > Signed-off-by: Pratyush Anand <panand at redhat.com>
>> > > ---
>> > > arch/x86_64.c  | 42 ++++++++----------------------------------
>> > > makedumpfile.h |  4 ++--
>> > > 2 files changed, 10 insertions(+), 36 deletions(-)
>> > >
>> > > diff --git a/arch/x86_64.c b/arch/x86_64.c
>> > > index a96fd8ae00a1..fe2764a8bec2 100644
>> > > --- a/arch/x86_64.c
>> > > +++ b/arch/x86_64.c
>> > > @@ -203,6 +203,12 @@ vtop4_x86_64(unsigned long vaddr)
>> > > {
>> > > 	unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
>> > > 	unsigned long pte_paddr, pte;
>> > > +	unsigned long phys_base;
>> > > +
>> > > +	if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
>> > > +		phys_base = info->phys_base;
>> > > +	else
>> > > +		phys_base = 0;
>> > >
>> > > 	if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
>> > > 		ERRMSG("Can't get the symbol of init_level4_pgt.\n");
>> > > @@ -212,9 +218,9 @@ vtop4_x86_64(unsigned long vaddr)
>> > > 	/*
>> > > 	 * Get PGD.
>> > > 	 */
>> > > -	page_dir  = SYMBOL(init_level4_pgt);
>> > > +	page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + phys_base;
>> >
>> > I want to confirm that this VA to PA translation is always safe,
>> > otherwise we should do the condition check which was done in
>> > vaddr_to_paddr_x86_64(), isn't it ?
>> >
>>
>> I think this should be safe, however x86 expert can comment better. Baoquan
>> any comment here?
>
>Yes, I think this is safe. Below is the physical to virtual address
>translation function in x86 64. And init_level4_pgt is a global variable
>located in kernel text region.
>
>arch/x86/include/asm/page_64.h
>
>static inline unsigned long __phys_addr_nodebug(unsigned long x)
>{
>        unsigned long y = x - __START_KERNEL_map;
>
>        /* use the carry flag to determine if x was < __START_KERNEL_map */
>        x = y + ((x > y) ? phys_base : (__START_KERNEL_map - PAGE_OFFSET));
>
>        return x;
>}

Good, thanks for your comment.
I'll wait for the result of the benchmark.

Regards,
Atsushi Kumagai


From smith.not.western at gmail.com  Wed Oct 26 06:52:50 2016
From: smith.not.western at gmail.com (Simon T)
Date: Wed, 26 Oct 2016 14:52:50 +0100
Subject: kexec and arm64 advice
In-Reply-To: <3118d747-8f11-fae5-9541-0fb0917eaa14@infradead.org>
References: <CAKYm0coteEEapCNwmj+KmGd57C_C3--nXQfjyD_FLoGXSkqMkQ@mail.gmail.com>
 <3118d747-8f11-fae5-9541-0fb0917eaa14@infradead.org>
Message-ID: <CAKYm0crtFkPh5iu3LNBZniFGNT2Xc0=WKO+=5_H_t+2+jNCBcw@mail.gmail.com>

On Tue, Oct 25, 2016 at 5:57 PM, Geoff Levand <geoff at infradead.org> wrote:
> On 10/24/2016 07:42 AM, Simon T wrote:
>> Both tools and kernel appear to build fine, however when it
>> comes time to kexec, I encounter this message: "kexec_load failed:
>> Function not implemented"
>
> It seems your kernel needs kexec support. Try something like:
>
>   cat /proc/config.gz | gunzip | egrep 'KEXEC'

Aha, yes you are correct it is not compiled in, even though it was in
my .config. I will investigate my config files and build scripts
further,

Thanks,

Simon


From gregkh at linuxfoundation.org  Wed Oct 26 05:22:45 2016
From: gregkh at linuxfoundation.org (Greg Kroah-Hartman)
Date: Wed, 26 Oct 2016 14:22:45 +0200
Subject: [PATCH 4.8 105/140] x86/boot/smp: Dont try to poke
 disabled/non-existent APIC
In-Reply-To: <20161026122220.384323763@linuxfoundation.org>
References: <20161026122220.384323763@linuxfoundation.org>
Message-ID: <20161026122224.880728927@linuxfoundation.org>

4.8-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Ville Syrj?l? <ville.syrjala at linux.intel.com>

commit ff8560512b8d4b7ca3ef4fd69166634ac30b2525 upstream.

Apparently trying to poke a disabled or non-existent APIC
leads to a box that doesn't even boot. Let's not do that.

No real clue if this is the right fix, but at least my
P3 machine boots again.

Signed-off-by: Ville Syrj?l? <ville.syrjala at linux.intel.com>
Cc: Andy Lutomirski <luto at kernel.org>
Cc: Borislav Petkov <bp at alien8.de>
Cc: Borislav Petkov <bp at suse.de>
Cc: Brian Gerst <brgerst at gmail.com>
Cc: Denys Vlasenko <dvlasenk at redhat.com>
Cc: Eric Biederman <ebiederm at xmission.com>
Cc: H. Peter Anvin <hpa at zytor.com>
Cc: Jiri Olsa <jolsa at redhat.com>
Cc: Josh Poimboeuf <jpoimboe at redhat.com>
Cc: Juergen Gross <jgross at suse.com>
Cc: Len Brown <len.brown at intel.com>
Cc: Linus Torvalds <torvalds at linux-foundation.org>
Cc: Peter Zijlstra <peterz at infradead.org>
Cc: Prarit Bhargava <prarit at redhat.com>
Cc: Thomas Gleixner <tglx at linutronix.de>
Cc: Yinghai Lu <yinghai at kernel.org>
Cc: dyoung at redhat.com
Cc: kexec at lists.infradead.org
Fixes: 2a51fe083eba ("arch/x86: Handle non enumerated CPU after physical hotplug")
Link: http://lkml.kernel.org/r/1477102684-5092-1-git-send-email-ville.syrjala at linux.intel.com
Signed-off-by: Ingo Molnar <mingo at kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>

---
 arch/x86/kernel/smpboot.c |   16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1408,15 +1408,17 @@ __init void prefill_possible_map(void)
 
 	/* No boot processor was found in mptable or ACPI MADT */
 	if (!num_processors) {
-		int apicid = boot_cpu_physical_apicid;
-		int cpu = hard_smp_processor_id();
+		if (boot_cpu_has(X86_FEATURE_APIC)) {
+			int apicid = boot_cpu_physical_apicid;
+			int cpu = hard_smp_processor_id();
 
-		pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu);
+			pr_warn("Boot CPU (id %d) not listed by BIOS\n", cpu);
 
-		/* Make sure boot cpu is enumerated */
-		if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
-		    apic->apic_id_valid(apicid))
-			generic_processor_info(apicid, boot_cpu_apic_version);
+			/* Make sure boot cpu is enumerated */
+			if (apic->cpu_present_to_apicid(0) == BAD_APICID &&
+			    apic->apic_id_valid(apicid))
+				generic_processor_info(apicid, boot_cpu_apic_version);
+		}
 
 		if (!num_processors)
 			num_processors = 1;




From geoff at infradead.org  Wed Oct 26 12:57:52 2016
From: geoff at infradead.org (Geoff Levand)
Date: Wed, 26 Oct 2016 12:57:52 -0700
Subject: [PATCH] arm64: Add support of R_AARCH64_PREL32 relocation in
 purgatory
In-Reply-To: <0eb8a908f617e0f957df7fb3ef293596f47e6832.1477456661.git.panand@redhat.com>
References: <0eb8a908f617e0f957df7fb3ef293596f47e6832.1477456661.git.panand@redhat.com>
Message-ID: <34a7177f-3bd8-8ccf-f928-36f89e9e29f2@infradead.org>

On 10/25/2016 09:40 PM, Pratyush Anand wrote:
> +	case R_AARCH64_PREL32:
> +		type = "PREL32";
> +		loc32 = ptr;
> +		*loc32 = cpu_to_elf32(ehdr, elf32_to_cpu(ehdr, *loc32) + value - address);

Please keep line width less than 80 chars.

> +		break;



From dyoung at redhat.com  Wed Oct 26 19:37:43 2016
From: dyoung at redhat.com (Dave Young)
Date: Thu, 27 Oct 2016 10:37:43 +0800
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <cover.1477327674.git.panand@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
Message-ID: <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>

Hi Pratyush,

On 10/24/16 at 10:18pm, Pratyush Anand wrote:
> Patch 1/4 fixes page_offset calculation, so that it is correctly calculated
> on KASLR enabled kernel as well.
> Patch 2/4 simplifies VA to PA translation. New code has been benchmarked
> against old code on a 4T system.
> Patch 3/4 and 4/4 is removal of (now) unnecessary code.
> 
> I think, we should find a way to kill find_vememmap() as well, so that
> VMEMMAP_START can be removed. I have very limited idea about x86, so unable
> to do that as of now.
> 
> Pratyush Anand (4):
>   x86_64: Calculate page_offset from pt_load
>   x86_64: translate all VA to PA using page table values
>   x86_64: kill is_vmalloc_addr_x86_64()
>   x86_64: kill some unused initialization
> 
>  arch/x86_64.c  | 84 ++++++++++++++++++++--------------------------------------
>  makedumpfile.h |  9 +++----
>  2 files changed, 32 insertions(+), 61 deletions(-)
> 

According to our test, with these patches the dumped vmcore is correct
which means simple crash test `bt` works. But the saved vmcore size is
larger than before.

I collected two --message-level 31 logs with/without your patches, the
kernel kaslr was disabled during my test so that we can focus on the
vmcore size issue, it looks like mem_map address was not collected
correctly.

[please ignore the patched log extra debug message I added] 

--- unpatched-makedumpfile.txt	2016-10-27 10:31:34.152962407 +0800
+++ patched-makedumpfile.txt	2016-10-27 10:28:44.213952179 +0800
@@ -1,4 +1,4 @@
-[127.0.0.1-2016-10-27-10:27:03]# /tmp/makedumpfile -l -d 31 --message-level 31 vmcore vmcore.m.1
+[127.0.0.1-2016-10-27-10:27:03]# /home/dyoung/git/makedumpfile/makedumpfile -l -d 31 --message-level 31 vmcore vmcore.m
 sadump: does not have partition header
 sadump: read dump device as unknown format
 sadump: unknown format
@@ -36,70 +36,76 @@
 
 Memory type  : SPARSEMEM_EX
 
+printing memmap .....
 mem_map (0)
-  mem_map    : ffffea0000000000
+  mem_map    : 0
   pfn_start  : 0
   pfn_end    : 8000
+printing memmap .....
 mem_map (1)
-  mem_map    : ffffea0000200000
+  mem_map    : 0
   pfn_start  : 8000
   pfn_end    : 10000
+printing memmap .....
 mem_map (2)
-  mem_map    : ffffea0000400000
+  mem_map    : 0
   pfn_start  : 10000
   pfn_end    : 18000
+printing memmap .....
 mem_map (3)
-  mem_map    : ffffea0000600000
+  mem_map    : 0
   pfn_start  : 18000
   pfn_end    : 20000
+printing memmap .....
 mem_map (4)
-  mem_map    : ffffea0000800000
+  mem_map    : 0
   pfn_start  : 20000
   pfn_end    : 28000
+printing memmap .....
 mem_map (5)
-  mem_map    : ffffea0000a00000
+  mem_map    : 0
   pfn_start  : 28000
   pfn_end    : 30000
+printing memmap .....
 mem_map (6)
-  mem_map    : ffffea0000c00000
+  mem_map    : 0
   pfn_start  : 30000
   pfn_end    : 38000
+printing memmap .....
 mem_map (7)
-  mem_map    : ffffea0000e00000
+  mem_map    : 0
   pfn_start  : 38000
   pfn_end    : 3ffda
 mmap() is available on the kernel.
 Checking for memory holes          : [100.0 %] |STEP [Checking for memory holes  ] : 0.000030 seconds
-Excluding unnecessary pages        : [100.0 %] \STEP [Excluding unnecessary pages] : 0.007547 seconds
-Checking for memory holes          : [100.0 %] -STEP [Checking for memory holes  ] : 0.000016 seconds
-Checking for memory holes          : [100.0 %] /STEP [Checking for memory holes  ] : 0.000009 seconds
-Excluding unnecessary pages        : [100.0 %] |STEP [Excluding unnecessary pages] : 0.006623 seconds
-Copying data                       : [100.0 %] \STEP [Copying data               ] : 0.184442 seconds
-Copying data                       : [100.0 %] -STEP [Copying data               ] : 0.000041 seconds
+Excluding unnecessary pages        : [100.0 %] \STEP [Excluding unnecessary pages] : 0.000007 seconds
+Checking for memory holes          : [100.0 %] -STEP [Checking for memory holes  ] : 0.000014 seconds
+Checking for memory holes          : [100.0 %] /STEP [Checking for memory holes  ] : 0.000008 seconds
+Excluding unnecessary pages        : [100.0 %] |STEP [Excluding unnecessary pages] : 0.000007 seconds
+Copying data                       : [100.0 %] /STEP [Copying data               ] : 1.421661 seconds
+Copying data                       : [100.0 %] |STEP [Copying data               ] : 0.000036 seconds
 
 Writing erase info...
-offset_eraseinfo: dd5c4e, size_eraseinfo: 0
+offset_eraseinfo: 888c149, size_eraseinfo: 0
 
 Original pages  : 0x0000000000030c7d
-  Excluded pages   : 0x000000000002cf58
-    Pages filled with zero  : 0x00000000000002be
-    Non-private cache pages : 0x0000000000006574
-    Private cache pages     : 0x0000000000000f27
-    User process data pages : 0x0000000000003481
-    Free pages              : 0x000000000002237e
+  Excluded pages   : 0x000000000001d534
+    Pages filled with zero  : 0x000000000001d534
+    Non-private cache pages : 0x0000000000000000
+    Private cache pages     : 0x0000000000000000
+    User process data pages : 0x0000000000000000
+    Free pages              : 0x0000000000000000
     Hwpoison pages          : 0x0000000000000000
-  Remaining pages  : 0x0000000000003d25
-  (The number of pages is reduced to 7%.)
+  Remaining pages  : 0x0000000000013749
+  (The number of pages is reduced to 39%.)
 Memory Hole     : 0x000000000000f35d
 --------------------------------------------------
 Total pages     : 0x000000000003ffda
 
-Cache hit: 29946, miss: 47, hit rate: 99.8%
+Cache hit: 196285, miss: 201, hit rate: 99.9%
 
 
-The dumpfile is saved to vmcore.m.1.
+The dumpfile is saved to vmcore.m.
 
 makedumpfile Completed.
-[root at dhcp-128-65 127.0.0.1-2016-10-27-10:27:03]# ls -lth vmcore.m*
--rw------- 1 root root  14M Oct 27 10:30 vmcore.m.1
--rw------- 1 root root 137M Oct 27 10:28 vmcore.m
+[root at dhcp-128-65 127.0.0.1-2016-10-27-10:27:03]# 


From dyoung at redhat.com  Wed Oct 26 19:54:37 2016
From: dyoung at redhat.com (Dave Young)
Date: Thu, 27 Oct 2016 10:54:37 +0800
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>
Message-ID: <20161027025437.GA20670@dhcp-128-65.nay.redhat.com>

I put the cped-vmcore/vmlinux here:
https://people.redhat.com/~ruyang/test/

Adding Dave Anderson for any comments about the vmcore correctness from
crash point of view..

On 10/27/16 at 10:37am, Dave Young wrote:
> Hi Pratyush,
> 
> On 10/24/16 at 10:18pm, Pratyush Anand wrote:
> > Patch 1/4 fixes page_offset calculation, so that it is correctly calculated
> > on KASLR enabled kernel as well.
> > Patch 2/4 simplifies VA to PA translation. New code has been benchmarked
> > against old code on a 4T system.
> > Patch 3/4 and 4/4 is removal of (now) unnecessary code.
> > 
> > I think, we should find a way to kill find_vememmap() as well, so that
> > VMEMMAP_START can be removed. I have very limited idea about x86, so unable
> > to do that as of now.
> > 
> > Pratyush Anand (4):
> >   x86_64: Calculate page_offset from pt_load
> >   x86_64: translate all VA to PA using page table values
> >   x86_64: kill is_vmalloc_addr_x86_64()
> >   x86_64: kill some unused initialization
> > 
> >  arch/x86_64.c  | 84 ++++++++++++++++++++--------------------------------------
> >  makedumpfile.h |  9 +++----
> >  2 files changed, 32 insertions(+), 61 deletions(-)
> > 
> 
> According to our test, with these patches the dumped vmcore is correct
> which means simple crash test `bt` works. But the saved vmcore size is
> larger than before.
> 
> I collected two --message-level 31 logs with/without your patches, the
> kernel kaslr was disabled during my test so that we can focus on the
> vmcore size issue, it looks like mem_map address was not collected
> correctly.
> 
> [please ignore the patched log extra debug message I added] 
> 
> --- unpatched-makedumpfile.txt	2016-10-27 10:31:34.152962407 +0800
> +++ patched-makedumpfile.txt	2016-10-27 10:28:44.213952179 +0800
> @@ -1,4 +1,4 @@
> -[127.0.0.1-2016-10-27-10:27:03]# /tmp/makedumpfile -l -d 31 --message-level 31 vmcore vmcore.m.1
> +[127.0.0.1-2016-10-27-10:27:03]# /home/dyoung/git/makedumpfile/makedumpfile -l -d 31 --message-level 31 vmcore vmcore.m
>  sadump: does not have partition header
>  sadump: read dump device as unknown format
>  sadump: unknown format
> @@ -36,70 +36,76 @@
>  
>  Memory type  : SPARSEMEM_EX
>  
> +printing memmap .....
>  mem_map (0)
> -  mem_map    : ffffea0000000000
> +  mem_map    : 0
>    pfn_start  : 0
>    pfn_end    : 8000
> +printing memmap .....
>  mem_map (1)
> -  mem_map    : ffffea0000200000
> +  mem_map    : 0
>    pfn_start  : 8000
>    pfn_end    : 10000
> +printing memmap .....
>  mem_map (2)
> -  mem_map    : ffffea0000400000
> +  mem_map    : 0
>    pfn_start  : 10000
>    pfn_end    : 18000
> +printing memmap .....
>  mem_map (3)
> -  mem_map    : ffffea0000600000
> +  mem_map    : 0
>    pfn_start  : 18000
>    pfn_end    : 20000
> +printing memmap .....
>  mem_map (4)
> -  mem_map    : ffffea0000800000
> +  mem_map    : 0
>    pfn_start  : 20000
>    pfn_end    : 28000
> +printing memmap .....
>  mem_map (5)
> -  mem_map    : ffffea0000a00000
> +  mem_map    : 0
>    pfn_start  : 28000
>    pfn_end    : 30000
> +printing memmap .....
>  mem_map (6)
> -  mem_map    : ffffea0000c00000
> +  mem_map    : 0
>    pfn_start  : 30000
>    pfn_end    : 38000
> +printing memmap .....
>  mem_map (7)
> -  mem_map    : ffffea0000e00000
> +  mem_map    : 0
>    pfn_start  : 38000
>    pfn_end    : 3ffda
>  mmap() is available on the kernel.
>  Checking for memory holes          : [100.0 %] |STEP [Checking for memory holes  ] : 0.000030 seconds
> -Excluding unnecessary pages        : [100.0 %] \STEP [Excluding unnecessary pages] : 0.007547 seconds
> -Checking for memory holes          : [100.0 %] -STEP [Checking for memory holes  ] : 0.000016 seconds
> -Checking for memory holes          : [100.0 %] /STEP [Checking for memory holes  ] : 0.000009 seconds
> -Excluding unnecessary pages        : [100.0 %] |STEP [Excluding unnecessary pages] : 0.006623 seconds
> -Copying data                       : [100.0 %] \STEP [Copying data               ] : 0.184442 seconds
> -Copying data                       : [100.0 %] -STEP [Copying data               ] : 0.000041 seconds
> +Excluding unnecessary pages        : [100.0 %] \STEP [Excluding unnecessary pages] : 0.000007 seconds
> +Checking for memory holes          : [100.0 %] -STEP [Checking for memory holes  ] : 0.000014 seconds
> +Checking for memory holes          : [100.0 %] /STEP [Checking for memory holes  ] : 0.000008 seconds
> +Excluding unnecessary pages        : [100.0 %] |STEP [Excluding unnecessary pages] : 0.000007 seconds
> +Copying data                       : [100.0 %] /STEP [Copying data               ] : 1.421661 seconds
> +Copying data                       : [100.0 %] |STEP [Copying data               ] : 0.000036 seconds
>  
>  Writing erase info...
> -offset_eraseinfo: dd5c4e, size_eraseinfo: 0
> +offset_eraseinfo: 888c149, size_eraseinfo: 0
>  
>  Original pages  : 0x0000000000030c7d
> -  Excluded pages   : 0x000000000002cf58
> -    Pages filled with zero  : 0x00000000000002be
> -    Non-private cache pages : 0x0000000000006574
> -    Private cache pages     : 0x0000000000000f27
> -    User process data pages : 0x0000000000003481
> -    Free pages              : 0x000000000002237e
> +  Excluded pages   : 0x000000000001d534
> +    Pages filled with zero  : 0x000000000001d534
> +    Non-private cache pages : 0x0000000000000000
> +    Private cache pages     : 0x0000000000000000
> +    User process data pages : 0x0000000000000000
> +    Free pages              : 0x0000000000000000
>      Hwpoison pages          : 0x0000000000000000
> -  Remaining pages  : 0x0000000000003d25
> -  (The number of pages is reduced to 7%.)
> +  Remaining pages  : 0x0000000000013749
> +  (The number of pages is reduced to 39%.)
>  Memory Hole     : 0x000000000000f35d
>  --------------------------------------------------
>  Total pages     : 0x000000000003ffda
>  
> -Cache hit: 29946, miss: 47, hit rate: 99.8%
> +Cache hit: 196285, miss: 201, hit rate: 99.9%
>  
>  
> -The dumpfile is saved to vmcore.m.1.
> +The dumpfile is saved to vmcore.m.
>  
>  makedumpfile Completed.
> -[root at dhcp-128-65 127.0.0.1-2016-10-27-10:27:03]# ls -lth vmcore.m*
> --rw------- 1 root root  14M Oct 27 10:30 vmcore.m.1
> --rw------- 1 root root 137M Oct 27 10:28 vmcore.m
> +[root at dhcp-128-65 127.0.0.1-2016-10-27-10:27:03]# 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From bhe at redhat.com  Wed Oct 26 20:25:48 2016
From: bhe at redhat.com (Baoquan He)
Date: Thu, 27 Oct 2016 11:25:48 +0800
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>
Message-ID: <20161027032548.GA5614@x1>

On 10/27/16 at 10:37am, Dave Young wrote:
> Hi Pratyush,
> 
> On 10/24/16 at 10:18pm, Pratyush Anand wrote:
> > Patch 1/4 fixes page_offset calculation, so that it is correctly calculated
> > on KASLR enabled kernel as well.
> > Patch 2/4 simplifies VA to PA translation. New code has been benchmarked
> > against old code on a 4T system.
> > Patch 3/4 and 4/4 is removal of (now) unnecessary code.
> > 
> > I think, we should find a way to kill find_vememmap() as well, so that
> > VMEMMAP_START can be removed. I have very limited idea about x86, so unable
> > to do that as of now.
> > 
> > Pratyush Anand (4):
> >   x86_64: Calculate page_offset from pt_load
> >   x86_64: translate all VA to PA using page table values
> >   x86_64: kill is_vmalloc_addr_x86_64()
> >   x86_64: kill some unused initialization
> > 
> >  arch/x86_64.c  | 84 ++++++++++++++++++++--------------------------------------
> >  makedumpfile.h |  9 +++----
> >  2 files changed, 32 insertions(+), 61 deletions(-)
> > 
> 
> According to our test, with these patches the dumped vmcore is correct
> which means simple crash test `bt` works. But the saved vmcore size is
> larger than before.
> 
> I collected two --message-level 31 logs with/without your patches, the
> kernel kaslr was disabled during my test so that we can focus on the
> vmcore size issue, it looks like mem_map address was not collected
> correctly.

>From printing log, this is not correct. Without memmap, filtering can't
be done correctly. 

> 
> [please ignore the patched log extra debug message I added] 
> 
> --- unpatched-makedumpfile.txt	2016-10-27 10:31:34.152962407 +0800
> +++ patched-makedumpfile.txt	2016-10-27 10:28:44.213952179 +0800
> @@ -1,4 +1,4 @@
> -[127.0.0.1-2016-10-27-10:27:03]# /tmp/makedumpfile -l -d 31 --message-level 31 vmcore vmcore.m.1
> +[127.0.0.1-2016-10-27-10:27:03]# /home/dyoung/git/makedumpfile/makedumpfile -l -d 31 --message-level 31 vmcore vmcore.m
>  sadump: does not have partition header
>  sadump: read dump device as unknown format
>  sadump: unknown format
> @@ -36,70 +36,76 @@
>  
>  Memory type  : SPARSEMEM_EX
>  
> +printing memmap .....
>  mem_map (0)
> -  mem_map    : ffffea0000000000
> +  mem_map    : 0
>    pfn_start  : 0
>    pfn_end    : 8000
> +printing memmap .....
>  mem_map (1)
> -  mem_map    : ffffea0000200000
> +  mem_map    : 0
>    pfn_start  : 8000
>    pfn_end    : 10000
> +printing memmap .....
>  mem_map (2)
> -  mem_map    : ffffea0000400000
> +  mem_map    : 0
>    pfn_start  : 10000
>    pfn_end    : 18000
> +printing memmap .....
>  mem_map (3)
> -  mem_map    : ffffea0000600000
> +  mem_map    : 0
>    pfn_start  : 18000
>    pfn_end    : 20000
> +printing memmap .....
>  mem_map (4)
> -  mem_map    : ffffea0000800000
> +  mem_map    : 0
>    pfn_start  : 20000
>    pfn_end    : 28000
> +printing memmap .....
>  mem_map (5)
> -  mem_map    : ffffea0000a00000
> +  mem_map    : 0
>    pfn_start  : 28000
>    pfn_end    : 30000
> +printing memmap .....
>  mem_map (6)
> -  mem_map    : ffffea0000c00000
> +  mem_map    : 0
>    pfn_start  : 30000
>    pfn_end    : 38000
> +printing memmap .....
>  mem_map (7)
> -  mem_map    : ffffea0000e00000
> +  mem_map    : 0
>    pfn_start  : 38000
>    pfn_end    : 3ffda
>  mmap() is available on the kernel.
>  Checking for memory holes          : [100.0 %] |STEP [Checking for memory holes  ] : 0.000030 seconds
> -Excluding unnecessary pages        : [100.0 %] \STEP [Excluding unnecessary pages] : 0.007547 seconds
> -Checking for memory holes          : [100.0 %] -STEP [Checking for memory holes  ] : 0.000016 seconds
> -Checking for memory holes          : [100.0 %] /STEP [Checking for memory holes  ] : 0.000009 seconds
> -Excluding unnecessary pages        : [100.0 %] |STEP [Excluding unnecessary pages] : 0.006623 seconds
> -Copying data                       : [100.0 %] \STEP [Copying data               ] : 0.184442 seconds
> -Copying data                       : [100.0 %] -STEP [Copying data               ] : 0.000041 seconds
> +Excluding unnecessary pages        : [100.0 %] \STEP [Excluding unnecessary pages] : 0.000007 seconds
> +Checking for memory holes          : [100.0 %] -STEP [Checking for memory holes  ] : 0.000014 seconds
> +Checking for memory holes          : [100.0 %] /STEP [Checking for memory holes  ] : 0.000008 seconds
> +Excluding unnecessary pages        : [100.0 %] |STEP [Excluding unnecessary pages] : 0.000007 seconds
> +Copying data                       : [100.0 %] /STEP [Copying data               ] : 1.421661 seconds
> +Copying data                       : [100.0 %] |STEP [Copying data               ] : 0.000036 seconds
>  
>  Writing erase info...
> -offset_eraseinfo: dd5c4e, size_eraseinfo: 0
> +offset_eraseinfo: 888c149, size_eraseinfo: 0
>  
>  Original pages  : 0x0000000000030c7d
> -  Excluded pages   : 0x000000000002cf58
> -    Pages filled with zero  : 0x00000000000002be
> -    Non-private cache pages : 0x0000000000006574
> -    Private cache pages     : 0x0000000000000f27
> -    User process data pages : 0x0000000000003481
> -    Free pages              : 0x000000000002237e
> +  Excluded pages   : 0x000000000001d534
> +    Pages filled with zero  : 0x000000000001d534
> +    Non-private cache pages : 0x0000000000000000
> +    Private cache pages     : 0x0000000000000000
> +    User process data pages : 0x0000000000000000
> +    Free pages              : 0x0000000000000000
>      Hwpoison pages          : 0x0000000000000000
> -  Remaining pages  : 0x0000000000003d25
> -  (The number of pages is reduced to 7%.)
> +  Remaining pages  : 0x0000000000013749
> +  (The number of pages is reduced to 39%.)
>  Memory Hole     : 0x000000000000f35d
>  --------------------------------------------------
>  Total pages     : 0x000000000003ffda
>  
> -Cache hit: 29946, miss: 47, hit rate: 99.8%
> +Cache hit: 196285, miss: 201, hit rate: 99.9%
>  
>  
> -The dumpfile is saved to vmcore.m.1.
> +The dumpfile is saved to vmcore.m.
>  
>  makedumpfile Completed.
> -[root at dhcp-128-65 127.0.0.1-2016-10-27-10:27:03]# ls -lth vmcore.m*
> --rw------- 1 root root  14M Oct 27 10:30 vmcore.m.1
> --rw------- 1 root root 137M Oct 27 10:28 vmcore.m
> +[root at dhcp-128-65 127.0.0.1-2016-10-27-10:27:03]# 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From panand at redhat.com  Wed Oct 26 22:11:23 2016
From: panand at redhat.com (Pratyush Anand)
Date: Thu, 27 Oct 2016 10:41:23 +0530
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>
Message-ID: <1d466d00-fe18-072d-b050-f2dcd29f7858@redhat.com>



On Thursday 27 October 2016 08:07 AM, Dave Young wrote:
> According to our test, with these patches the dumped vmcore is correct
> which means simple crash test `bt` works. But the saved vmcore size is
> larger than before.
>
> I collected two --message-level 31 logs with/without your patches, the
> kernel kaslr was disabled during my test so that we can focus on the
> vmcore size issue, it looks like mem_map address was not collected
> correctly.
>
> [please ignore the patched log extra debug message I added]

Hummm..thanks for pointing it out.

Seems patch 1/4 is wrong.

with this patch page_offset = ffffffff80000000
while with original code page_offset = ffff880000000000

Trying to see where it is wrong

~Pratyush


From panand at redhat.com  Wed Oct 26 23:03:36 2016
From: panand at redhat.com (Pratyush Anand)
Date: Thu, 27 Oct 2016 11:33:36 +0530
Subject: [PATCH Makedumpfile 1/4] x86_64: Calculate page_offset from
 pt_load
In-Reply-To: <4b2497eff40bd47eef59cdd6af165e700cfd4408.1477327674.git.panand@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <4b2497eff40bd47eef59cdd6af165e700cfd4408.1477327674.git.panand@redhat.com>
Message-ID: <c873178b-4d1b-03a2-f419-f2dc6602a5cc@redhat.com>



On Monday 24 October 2016 10:18 PM, Pratyush Anand wrote:
> page_offset can always be calculated as 'virtual - physical' for a direct
> mapping area on x86. Therefore, remove the version dependent calculation
> and use this method.
>
> Signed-off-by: Pratyush Anand <panand at redhat.com>
> ---
>  arch/x86_64.c | 24 ++++++++++++++++++++----
>  1 file changed, 20 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86_64.c b/arch/x86_64.c
> index ddf7be6bc57b..a96fd8ae00a1 100644
> --- a/arch/x86_64.c
> +++ b/arch/x86_64.c
> @@ -44,6 +44,24 @@ get_xen_p2m_mfn(void)
>  	return NOT_FOUND_LONG_VALUE;
>  }
>
> +static int
> +get_page_offset_x86_64(void)
> +{
> +	int i;
> +	unsigned long long phys_start;
> +	unsigned long long virt_start;
> +
> +	for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
> +		if (virt_start >= __START_KERNEL_map) {

OK..So, this is the problem. We should have

if (virt_start < __START_KERNEL_map) {

Kernel text region lies above __START_KERNEL_map, which is linearly 
mapped however not a direct mapping. Direct mapping region lies below it 
instead. So, page_offset can only be calculated with a region which is 
below __START_KERNEL_map.

Thanks Baoquan for finding it.

~Pratyush

> +			info->page_offset = virt_start - phys_start;
> +			return TRUE;
> +		}
> +	}
> +
> +	ERRMSG("Can't get any pt_load to calculate page offset.\n");
> +	return FALSE;
> +}
> +
>  int
>  get_phys_base_x86_64(void)
>  {
> @@ -159,10 +177,8 @@ get_versiondep_info_x86_64(void)
>  	else
>  		info->max_physmem_bits  = _MAX_PHYSMEM_BITS_2_6_31;
>
> -	if (info->kernel_version < KERNEL_VERSION(2, 6, 27))
> -		info->page_offset = __PAGE_OFFSET_ORIG;
> -	else
> -		info->page_offset = __PAGE_OFFSET_2_6_27;
> +	if (!get_page_offset_x86_64())
> +		return FALSE;
>
>  	if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
>  		info->vmalloc_start = VMALLOC_START_ORIG;
>


From dyoung at redhat.com  Wed Oct 26 23:19:45 2016
From: dyoung at redhat.com (Dave Young)
Date: Thu, 27 Oct 2016 14:19:45 +0800
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <20161027025437.GA20670@dhcp-128-65.nay.redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>
 <20161027025437.GA20670@dhcp-128-65.nay.redhat.com>
Message-ID: <20161027061945.GA23354@dhcp-128-65.nay.redhat.com>

On 10/27/16 at 10:54am, Dave Young wrote:
> I put the cped-vmcore/vmlinux here:
> https://people.redhat.com/~ruyang/test/
> 
> Adding Dave Anderson for any comments about the vmcore correctness from
> crash point of view..
> 

Since the reason has been found, the page_offset was not correct, I
tested with a changed version of patch 1, it works. Please ignore the
test vmcore, I deleted them.

Here is a new tarball which could be used by Dave to verify the kaslr, I
enabled kaslr, also saved vmlinux/cped vmcore/makedumpfile saved vmcore
in a tarball below.
http://people.redhat.com/~ruyang/test/vmcore-test.tar.gz

Thanks
Dave


From anderson at redhat.com  Thu Oct 27 06:25:18 2016
From: anderson at redhat.com (Dave Anderson)
Date: Thu, 27 Oct 2016 09:25:18 -0400 (EDT)
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <mailman.65015.1477545113.1639.kexec@lists.infradead.org>
References: <mailman.65015.1477545113.1639.kexec@lists.infradead.org>
Message-ID: <2004107674.8566432.1477574718303.JavaMail.zimbra@redhat.com>



----- Original Message -----
> 
> I put the cped-vmcore/vmlinux here:
> https://people.redhat.com/~ruyang/test/
> 
> Adding Dave Anderson for any comments about the vmcore correctness from
> crash point of view..
> 

As it turns out, the vmcore.makedumpfile can be read just fine:

  $ crash vmlinux.kaslr vmcore.makedumpfile 
  
  crash 7.1.7rc9
  Copyright (C) 2002-2016  Red Hat, Inc.
  Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
  Copyright (C) 1999-2006  Hewlett-Packard Co
  Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
  Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
  Copyright (C) 2005, 2011  NEC Corporation
  Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
  Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
  This program is free software, covered by the GNU General Public License,
  and you are welcome to change it and/or distribute copies of it under
  certain conditions.  Enter "help copying" to see the conditions.
  This program has absolutely no warranty.  Enter "help warranty" for details.
   
  GNU gdb (GDB) 7.6
  Copyright (C) 2013 Free Software Foundation, Inc.
  License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  This is free software: you are free to change and redistribute it.
  There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
  and "show warranty" for details.
  This GDB was configured as "x86_64-unknown-linux-gnu"...
  
  WARNING: kernel relocated [602MB]: patching 55325 gdb minimal_symbol values
  
        KERNEL: vmlinux.kaslr                                            
      DUMPFILE: vmcore.makedumpfile  [PARTIAL DUMP]
          CPUS: 1
          DATE: Thu Oct 27 02:07:46 2016
        UPTIME: 00:00:41
  LOAD AVERAGE: 0.14, 0.04, 0.01
         TASKS: 107
      NODENAME: localhost.localdomain
       RELEASE: 4.9.0-rc2+
       VERSION: #185 SMP Wed Oct 26 11:23:54 CST 2016
       MACHINE: x86_64  (2294 Mhz)
        MEMORY: 1 GB
         PANIC: "sysrq: SysRq : Trigger a crash"
           PID: 1934
       COMMAND: "bash"
          TASK: ffff9ca3bc155e00  [THREAD_INFO: ffff9ca3bc155e00]
           CPU: 0
         STATE: TASK_RUNNING (SYSRQ)
  
  crash> bt
  PID: 1934   TASK: ffff9ca3bc155e00  CPU: 0   COMMAND: "bash"
   #0 [ffffb2df4033fa08] machine_kexec at ffffffffa6a34e09
   #1 [ffffb2df4033fa68] __crash_kexec at ffffffffa6ab945a
   #2 [ffffb2df4033fb30] __crash_kexec at ffffffffa6ab9530
   #3 [ffffb2df4033fb48] crash_kexec at ffffffffa6ab9576
   #4 [ffffb2df4033fb68] oops_end at ffffffffa6a1529f
   #5 [ffffb2df4033fb90] no_context at ffffffffa6a3f67b
   #6 [ffffb2df4033fbf8] __bad_area_nosemaphore at ffffffffa6a3f8cc
   #7 [ffffb2df4033fc48] bad_area at ffffffffa6a3fa71
   #8 [ffffb2df4033fc70] __do_page_fault at ffffffffa6a4004d
   #9 [ffffb2df4033fcd8] do_page_fault at ffffffffa6a40100
  #10 [ffffb2df4033fd08] do_async_page_fault at ffffffffa6a3bbc5
  #11 [ffffb2df4033fd20] async_page_fault at ffffffffa6f9f1e5
      [exception RIP: sysrq_handle_crash+17]
      RIP: ffffffffa6d3a101  RSP: ffffb2df4033fdd8  RFLAGS: 00010282
      RAX: 000000000000000f  RBX: 0000000000000063  RCX: 0000000000000000
      RDX: 0000000000000000  RSI: ffff9ca3be60cc28  RDI: 0000000000000063
      RBP: ffffb2df4033fdd8   R8: 0000000000000001   R9: 0000000000000006
      R10: 0000000000000001  R11: 0000000000000172  R12: 0000000000000007
      R13: 0000000000000000  R14: ffffffffa745b4a0  R15: 0000000000000000
      ORIG_RAX: ffffffffffffffff  CS: 0010  SS: 0018
  #12 [ffffb2df4033fde0] __handle_sysrq at ffffffffa6d3a821
  #13 [ffffb2df4033fe10] write_sysrq_trigger at ffffffffa6d3ac4a
  #14 [ffffb2df4033fe28] proc_reg_write at ffffffffa6bb73dd
  #15 [ffffb2df4033fe48] __vfs_write at ffffffffa6b55b02
  #16 [ffffb2df4033fed0] vfs_write at ffffffffa6b56dbc
  #17 [ffffb2df4033ff08] sys_write at ffffffffa6b58060
  #18 [ffffb2df4033ff50] entry_SYSCALL_64_fastpath at ffffffffa6f9dbbb
      RIP: 00007f0b401a9c20  RSP: 00007ffe38d75698  RFLAGS: 00000246
      RAX: ffffffffffffffda  RBX: 0000000000000000  RCX: 00007f0b401a9c20
      RDX: 0000000000000002  RSI: 00005577bf7de790  RDI: 0000000000000001
      RBP: 0000000000000001   R8: 00007f0b40474740   R9: 00007f0b40ab7b40
      R10: 0000000000000073  R11: 0000000000000246  R12: 0000000000000000
      R13: 00007ffe38d75c10  R14: 0000000000000000  R15: 0000000000000000
      ORIG_RAX: 0000000000000001  CS: 0033  SS: 002b
  crash> 
  
But the ELF vmcore fails:
  
  $ crash vmlinux.kaslr vmcore
  
  crash 7.1.7rc9
  Copyright (C) 2002-2016  Red Hat, Inc.
  Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
  Copyright (C) 1999-2006  Hewlett-Packard Co
  Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
  Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
  Copyright (C) 2005, 2011  NEC Corporation
  Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
  Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
  This program is free software, covered by the GNU General Public License,
  and you are welcome to change it and/or distribute copies of it under
  certain conditions.  Enter "help copying" to see the conditions.
  This program has absolutely no warranty.  Enter "help warranty" for details.
   
  GNU gdb (GDB) 7.6
  Copyright (C) 2013 Free Software Foundation, Inc.
  License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  This is free software: you are free to change and redistribute it.
  There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
  and "show warranty" for details.
  This GDB was configured as "x86_64-unknown-linux-gnu"...
  
  WARNING: kernel relocated [602MB]: patching 55325 gdb minimal_symbol values
  
  WARNING: could not find MAGIC_START!                                   
  WARNING: cannot read linux_banner string
  crash: vmlinux.kaslr and vmcore do not match!
  
  Usage:
  
    crash [OPTION]... NAMELIST MEMORY-IMAGE[@ADDRESS]	(dumpfile form)
    crash [OPTION]... [NAMELIST]             		(live system form)
  
  Enter "crash -h" for details.
  $
  
Since the data being read was bogus, the first thing I checked was whether
the phys_base value was being calculated correctly.  I manually applied 
the phys_base that was stored in the compressed dump header, and the ELF
vmcore can be read:

  $ crash --machdep phys_base=ffffffffdf400000 vmlinux.kaslr vmcore 
  
  crash 7.1.7rc9
  Copyright (C) 2002-2016  Red Hat, Inc.
  Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
  Copyright (C) 1999-2006  Hewlett-Packard Co
  Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
  Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
  Copyright (C) 2005, 2011  NEC Corporation
  Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
  Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
  This program is free software, covered by the GNU General Public License,
  and you are welcome to change it and/or distribute copies of it under
  certain conditions.  Enter "help copying" to see the conditions.
  This program has absolutely no warranty.  Enter "help warranty" for details.
   
  NOTE: setting phys_base to: 0xffffffffdf400000
  
  GNU gdb (GDB) 7.6
  Copyright (C) 2013 Free Software Foundation, Inc.
  License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  This is free software: you are free to change and redistribute it.
  There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
  and "show warranty" for details.
  This GDB was configured as "x86_64-unknown-linux-gnu"...
  
  WARNING: kernel relocated [602MB]: patching 55325 gdb minimal_symbol values
  
        KERNEL: vmlinux.kaslr                                            
      DUMPFILE: vmcore
          CPUS: 1
          DATE: Thu Oct 27 02:07:46 2016
        UPTIME: 00:00:41
  LOAD AVERAGE: 0.14, 0.04, 0.01
         TASKS: 107
      NODENAME: localhost.localdomain
       RELEASE: 4.9.0-rc2+
       VERSION: #185 SMP Wed Oct 26 11:23:54 CST 2016
       MACHINE: x86_64  (2294 Mhz)
        MEMORY: 1 GB
         PANIC: "sysrq: SysRq : Trigger a crash"
           PID: 1934
       COMMAND: "bash"
          TASK: ffff9ca3bc155e00  [THREAD_INFO: ffff9ca3bc155e00]
           CPU: 0
         STATE: TASK_RUNNING (SYSRQ)
  
  crash> 
  
That being said, my recent 4.8 and 4.9 KASLR testing has been on live
systems and compressed kdumps, so the old tried-and-true manner of
calculating the phys_base from the ELF PT_LOAD segments apparently
no longer works with KASLR.  

It would be so much more helpful if the VMCOREINFO data in the ELF 
header stored the actual phys_base value instead of its symbol value:

  crash> help -D
  ...
  SYMBOL(phys_base)=ffffffffa740b010
  ...

which is completely useless unless the phys_base value is known.

Anyway, can you send me the makedumpfile code that calculates the 
phys_base value?

Dave


From anderson at redhat.com  Thu Oct 27 08:25:20 2016
From: anderson at redhat.com (Dave Anderson)
Date: Thu, 27 Oct 2016 11:25:20 -0400 (EDT)
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <926225735.8567580.1477574985798.JavaMail.zimbra@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>
 <20161027025437.GA20670@dhcp-128-65.nay.redhat.com>
 <20161027061945.GA23354@dhcp-128-65.nay.redhat.com>
 <926225735.8567580.1477574985798.JavaMail.zimbra@redhat.com>
Message-ID: <595835228.8595706.1477581920601.JavaMail.zimbra@redhat.com>



----- Original Message -----

>   
> That being said, my recent 4.8 and 4.9 KASLR testing has been on live
> systems and compressed kdumps, so the old tried-and-true manner of
> calculating the phys_base from the ELF PT_LOAD segments apparently
> no longer works with KASLR.
> 
> It would be so much more helpful if the VMCOREINFO data in the ELF
> header stored the actual phys_base value instead of its symbol value:
> 
>   crash> help -D
>   ...
>   SYMBOL(phys_base)=ffffffffa740b010
>   ...
> 
> which is completely useless unless the phys_base value is known.
> 
> Anyway, can you send me the makedumpfile code that calculates the
> phys_base value?
> 
> Dave

As it turns out, the problem with the crash utility is that it has to
calculate phys_base well before it even knows the kernel has been relocated 
by KASLR.  So when it sees the __START_KERNEL_map PT_LOAD segment, it mistakes
it for the kernel modules' virtual address region and skips it.

The kernel has this:

  #if defined(CONFIG_RANDOMIZE_BASE)
  #define KERNEL_IMAGE_SIZE       (1024 * 1024 * 1024)
  #else
  #define KERNEL_IMAGE_SIZE       (512 * 1024 * 1024)
  #endif

and then this:

  #define MODULES_VADDR    (__START_KERNEL_map + KERNEL_IMAGE_SIZE)

So with KASLR, MODULES_VADDR gets pushed up from the traditional ffffffffa0000000
up to ffffffffc0000000.

So I'm curious as to what you use in makedumpfile to determine whether 
CONFIG_RANDOMIZE_BASE has been configured?

Thanks,
  Dave




From anderson at redhat.com  Thu Oct 27 08:41:51 2016
From: anderson at redhat.com (Dave Anderson)
Date: Thu, 27 Oct 2016 11:41:51 -0400 (EDT)
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <595835228.8595706.1477581920601.JavaMail.zimbra@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>
 <20161027025437.GA20670@dhcp-128-65.nay.redhat.com>
 <20161027061945.GA23354@dhcp-128-65.nay.redhat.com>
 <926225735.8567580.1477574985798.JavaMail.zimbra@redhat.com>
 <595835228.8595706.1477581920601.JavaMail.zimbra@redhat.com>
Message-ID: <1344182812.8599658.1477582911159.JavaMail.zimbra@redhat.com>



----- Original Message -----
> 
> 
> ----- Original Message -----
> 
> >   
> > That being said, my recent 4.8 and 4.9 KASLR testing has been on live
> > systems and compressed kdumps, so the old tried-and-true manner of
> > calculating the phys_base from the ELF PT_LOAD segments apparently
> > no longer works with KASLR.
> > 
> > It would be so much more helpful if the VMCOREINFO data in the ELF
> > header stored the actual phys_base value instead of its symbol value:
> > 
> >   crash> help -D
> >   ...
> >   SYMBOL(phys_base)=ffffffffa740b010
> >   ...
> > 
> > which is completely useless unless the phys_base value is known.
> > 
> > Anyway, can you send me the makedumpfile code that calculates the
> > phys_base value?
> > 
> > Dave
> 
> As it turns out, the problem with the crash utility is that it has to
> calculate phys_base well before it even knows the kernel has been relocated
> by KASLR.  So when it sees the __START_KERNEL_map PT_LOAD segment, it
> mistakes
> it for the kernel modules' virtual address region and skips it.
> 
> The kernel has this:
> 
>   #if defined(CONFIG_RANDOMIZE_BASE)
>   #define KERNEL_IMAGE_SIZE       (1024 * 1024 * 1024)
>   #else
>   #define KERNEL_IMAGE_SIZE       (512 * 1024 * 1024)
>   #endif
> 
> and then this:
> 
>   #define MODULES_VADDR    (__START_KERNEL_map + KERNEL_IMAGE_SIZE)
> 
> So with KASLR, MODULES_VADDR gets pushed up from the traditional ffffffffa0000000
> up to ffffffffc0000000.
> 
> So I'm curious as to what you use in makedumpfile to determine whether
> CONFIG_RANDOMIZE_BASE has been configured?
> 
> Thanks,
>   Dave

Hey, sorry, I didn't notice that this was added upstream:

  commit 1303a27c9c32020a3b6ac89be270d2ab1f28be24
  Author: Baoquan He <bhe at redhat.com>
  Date:   Wed Sep 9 15:39:03 2015 -0700

    kexec: export KERNEL_IMAGE_SIZE to vmcoreinfo
    
With that in place, it will be an easy fix for the crash utility.

Thanks,
  Dave











From panand at redhat.com  Thu Oct 27 08:59:27 2016
From: panand at redhat.com (Pratyush Anand)
Date: Thu, 27 Oct 2016 21:29:27 +0530
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <595835228.8595706.1477581920601.JavaMail.zimbra@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>
 <20161027025437.GA20670@dhcp-128-65.nay.redhat.com>
 <20161027061945.GA23354@dhcp-128-65.nay.redhat.com>
 <926225735.8567580.1477574985798.JavaMail.zimbra@redhat.com>
 <595835228.8595706.1477581920601.JavaMail.zimbra@redhat.com>
Message-ID: <56d182b4-73b6-4d16-4d5a-bd527cff944d@redhat.com>



On Thursday 27 October 2016 08:55 PM, Dave Anderson wrote:
> As it turns out, the problem with the crash utility is that it has to
> calculate phys_base well before it even knows the kernel has been relocated
> by KASLR.  So when it sees the __START_KERNEL_map PT_LOAD segment, it mistakes
> it for the kernel modules' virtual address region and skips it.
>
> The kernel has this:
>
>   #if defined(CONFIG_RANDOMIZE_BASE)
>   #define KERNEL_IMAGE_SIZE       (1024 * 1024 * 1024)
>   #else
>   #define KERNEL_IMAGE_SIZE       (512 * 1024 * 1024)
>   #endif
>
> and then this:
>
>   #define MODULES_VADDR    (__START_KERNEL_map + KERNEL_IMAGE_SIZE)
>
> So with KASLR, MODULES_VADDR gets pushed up from the traditional ffffffffa0000000
> up to ffffffffc0000000.
>
> So I'm curious as to what you use in makedumpfile to determine whether
> CONFIG_RANDOMIZE_BASE has been configured?

So far we are trying to avoid to know that in makedumpfile. makedumpfile 
needed to know MODULES_VADDR, VMALLOC_START etc only to know that 
whether a VA to PA translation can be done using direct mapping or to be 
done by reading corresponding page table entry.

Now, we do VA to PA for all VAs using page table entry only.

https://github.com/pratyushanand/makedumpfile/blob/x86_devel/arch/x86_64.c#L186

~Pratyush


From dyoung at redhat.com  Thu Oct 27 19:04:19 2016
From: dyoung at redhat.com (Dave Young)
Date: Fri, 28 Oct 2016 10:04:19 +0800
Subject: [PATCH Makedumpfile 0/4] x86_64: Fix page_offset for randomized
 base enabled
In-Reply-To: <1344182812.8599658.1477582911159.JavaMail.zimbra@redhat.com>
References: <cover.1477327674.git.panand@redhat.com>
 <20161027023743.GA20446@dhcp-128-65.nay.redhat.com>
 <20161027025437.GA20670@dhcp-128-65.nay.redhat.com>
 <20161027061945.GA23354@dhcp-128-65.nay.redhat.com>
 <926225735.8567580.1477574985798.JavaMail.zimbra@redhat.com>
 <595835228.8595706.1477581920601.JavaMail.zimbra@redhat.com>
 <1344182812.8599658.1477582911159.JavaMail.zimbra@redhat.com>
Message-ID: <20161028020419.GA3901@dhcp-128-65.nay.redhat.com>

On 10/27/16 at 11:41am, Dave Anderson wrote:
> 
> 
> ----- Original Message -----
> > 
> > 
> > ----- Original Message -----
> > 
> > >   
> > > That being said, my recent 4.8 and 4.9 KASLR testing has been on live
> > > systems and compressed kdumps, so the old tried-and-true manner of
> > > calculating the phys_base from the ELF PT_LOAD segments apparently
> > > no longer works with KASLR.
> > > 
> > > It would be so much more helpful if the VMCOREINFO data in the ELF
> > > header stored the actual phys_base value instead of its symbol value:
> > > 
> > >   crash> help -D
> > >   ...
> > >   SYMBOL(phys_base)=ffffffffa740b010
> > >   ...
> > > 
> > > which is completely useless unless the phys_base value is known.
> > > 
> > > Anyway, can you send me the makedumpfile code that calculates the
> > > phys_base value?
> > > 
> > > Dave
> > 
> > As it turns out, the problem with the crash utility is that it has to
> > calculate phys_base well before it even knows the kernel has been relocated
> > by KASLR.  So when it sees the __START_KERNEL_map PT_LOAD segment, it
> > mistakes
> > it for the kernel modules' virtual address region and skips it.
> > 
> > The kernel has this:
> > 
> >   #if defined(CONFIG_RANDOMIZE_BASE)
> >   #define KERNEL_IMAGE_SIZE       (1024 * 1024 * 1024)
> >   #else
> >   #define KERNEL_IMAGE_SIZE       (512 * 1024 * 1024)
> >   #endif
> > 
> > and then this:
> > 
> >   #define MODULES_VADDR    (__START_KERNEL_map + KERNEL_IMAGE_SIZE)
> > 
> > So with KASLR, MODULES_VADDR gets pushed up from the traditional ffffffffa0000000
> > up to ffffffffc0000000.
> > 
> > So I'm curious as to what you use in makedumpfile to determine whether
> > CONFIG_RANDOMIZE_BASE has been configured?
> > 
> > Thanks,
> >   Dave
> 
> Hey, sorry, I didn't notice that this was added upstream:
> 
>   commit 1303a27c9c32020a3b6ac89be270d2ab1f28be24
>   Author: Baoquan He <bhe at redhat.com>
>   Date:   Wed Sep 9 15:39:03 2015 -0700
> 
>     kexec: export KERNEL_IMAGE_SIZE to vmcoreinfo
>     
> With that in place, it will be an easy fix for the crash utility.

Dave, I confirmed your fix in crash git tree works, it also works for
the elf format vmcore, /proc/vmcore and makedumpfile -E created vmcore.

Thanks for the quick fix..

> 
> Thanks,
>   Dave
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From panand at redhat.com  Thu Oct 27 21:16:09 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 28 Oct 2016 09:46:09 +0530
Subject: [PATCH V2] arm64: Add support of R_AARCH64_PREL32 relocation in
 purgatory
Message-ID: <f970f7938109c40833fc45e3d6d72b1dcdf14595.1477627895.git.panand@redhat.com>

gcc version in fedora koji is  6.2.1-2.fc25. kexec-tools compiled with this
gcc produced another relocation error:

machine_apply_elf_rel: ERROR Unknown type: 261

This patch fixes the above error.

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
v1 -> v2: fixed line width to less than 80 chars

 kexec/arch/arm64/kexec-arm64.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c
index 218f0bc832cd..eb0c3b87354e 100644
--- a/kexec/arch/arm64/kexec-arm64.c
+++ b/kexec/arch/arm64/kexec-arm64.c
@@ -720,6 +720,10 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 # define R_AARCH64_ABS64 257
 #endif
 
+#if !defined(R_AARCH64_PREL32)
+# define R_AARCH64_PREL32 261
+#endif
+
 #if !defined(R_AARCH64_LD_PREL_LO19)
 # define R_AARCH64_LD_PREL_LO19 273
 #endif
@@ -761,6 +765,12 @@ void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym),
 		loc64 = ptr;
 		*loc64 = cpu_to_elf64(ehdr, elf64_to_cpu(ehdr, *loc64) + value);
 		break;
+	case R_AARCH64_PREL32:
+		type = "PREL32";
+		loc32 = ptr;
+		*loc32 = cpu_to_elf32(ehdr,
+			elf32_to_cpu(ehdr, *loc32) + value - address);
+		break;
 	case R_AARCH64_LD_PREL_LO19:
 		type = "LD_PREL_LO19";
 		loc32 = ptr;
-- 
2.7.4



From kamalesh at linux.vnet.ibm.com  Thu Oct 27 22:07:14 2016
From: kamalesh at linux.vnet.ibm.com (Kamalesh Babulal)
Date: Fri, 28 Oct 2016 10:37:14 +0530
Subject: [PATCH] Fix module module_init/init_size offsets for v4.5 kernel
Message-ID: <1477631234-15500-1-git-send-email-kamalesh@linux.vnet.ibm.com>

Kernel commit 7523e4dc50 (module: use a structure to encapsulate layout.)
encapsulates core_layout and init_layout into module_layout structure.

commit fa6a75a93 (Fix module core base and size offset for kernel v4.5)
fixes offset value calculation for core layout's base and size, whereas
Kernel v4.5 module changes also needs fixing of module init_size and
module_init for the makedumpfile to read the correct module address.

This patch fixes calculation of offsets values for module init_size and
module_init.

Signed-off-by: Kamalesh Babulal <kamalesh at linux.vnet.ibm.com>
Cc: Pratyush Anand <panand at redhat.com>
---
 makedumpfile.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/makedumpfile.c b/makedumpfile.c
index 853b999..f33a90d 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -1689,7 +1689,25 @@ get_structure_info(void)
 		OFFSET(module.core_size) += core_layout;
 	}
 	OFFSET_INIT(module.module_init, "module", "module_init");
+	if (OFFSET(module.module_init) == NOT_FOUND_STRUCTURE) {
+		/* for kernel version 4.5 and above */
+		long init_layout;
+
+		OFFSET_INIT(module.module_init, "module", "init_layout");
+		init_layout = OFFSET(module.module_init);
+		OFFSET_INIT(module.module_init, "module_layout", "base");
+		OFFSET(module.module_init) += init_layout;
+	}
 	OFFSET_INIT(module.init_size, "module", "init_size");
+	if (OFFSET(module.init_size) == NOT_FOUND_STRUCTURE) {
+		/* for kernel version 4.5 and above */
+		long init_layout;
+
+		OFFSET_INIT(module.init_size, "module", "init_layout");
+		init_layout = OFFSET(module.init_size);
+		OFFSET_INIT(module.init_size, "module_layout", "size");
+		OFFSET(module.init_size) += init_layout;
+	}
 
 	ENUM_NUMBER_INIT(NR_FREE_PAGES, "NR_FREE_PAGES");
 	ENUM_NUMBER_INIT(N_ONLINE, "N_ONLINE");
-- 
2.7.4



From panand at redhat.com  Thu Oct 27 23:17:55 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 28 Oct 2016 11:47:55 +0530
Subject: [PATCH] Fix module module_init/init_size offsets for v4.5 kernel
In-Reply-To: <1477631234-15500-1-git-send-email-kamalesh@linux.vnet.ibm.com>
References: <1477631234-15500-1-git-send-email-kamalesh@linux.vnet.ibm.com>
Message-ID: <07a394ec-5a25-9e0a-b0ac-3e931a589905@redhat.com>



On Friday 28 October 2016 10:37 AM, Kamalesh Babulal wrote:
> Kernel commit 7523e4dc50 (module: use a structure to encapsulate layout.)
> encapsulates core_layout and init_layout into module_layout structure.
>
> commit fa6a75a93 (Fix module core base and size offset for kernel v4.5)
> fixes offset value calculation for core layout's base and size, whereas
> Kernel v4.5 module changes also needs fixing of module init_size and
> module_init for the makedumpfile to read the correct module address.
>
> This patch fixes calculation of offsets values for module init_size and
> module_init.
>
> Signed-off-by: Kamalesh Babulal <kamalesh at linux.vnet.ibm.com>
> Cc: Pratyush Anand <panand at redhat.com>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  makedumpfile.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>
> diff --git a/makedumpfile.c b/makedumpfile.c
> index 853b999..f33a90d 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -1689,7 +1689,25 @@ get_structure_info(void)
>  		OFFSET(module.core_size) += core_layout;
>  	}
>  	OFFSET_INIT(module.module_init, "module", "module_init");
> +	if (OFFSET(module.module_init) == NOT_FOUND_STRUCTURE) {
> +		/* for kernel version 4.5 and above */
> +		long init_layout;
> +
> +		OFFSET_INIT(module.module_init, "module", "init_layout");
> +		init_layout = OFFSET(module.module_init);
> +		OFFSET_INIT(module.module_init, "module_layout", "base");
> +		OFFSET(module.module_init) += init_layout;
> +	}
>  	OFFSET_INIT(module.init_size, "module", "init_size");
> +	if (OFFSET(module.init_size) == NOT_FOUND_STRUCTURE) {
> +		/* for kernel version 4.5 and above */
> +		long init_layout;
> +
> +		OFFSET_INIT(module.init_size, "module", "init_layout");
> +		init_layout = OFFSET(module.init_size);
> +		OFFSET_INIT(module.init_size, "module_layout", "size");
> +		OFFSET(module.init_size) += init_layout;
> +	}
>
>  	ENUM_NUMBER_INIT(NR_FREE_PAGES, "NR_FREE_PAGES");
>  	ENUM_NUMBER_INIT(N_ONLINE, "N_ONLINE");
>


From panand at redhat.com  Thu Oct 27 23:18:10 2016
From: panand at redhat.com (Pratyush Anand)
Date: Fri, 28 Oct 2016 11:48:10 +0530
Subject: [PATCH] Fix module module_init/init_size offsets for v4.5 kernel
In-Reply-To: <1477631234-15500-1-git-send-email-kamalesh@linux.vnet.ibm.com>
References: <1477631234-15500-1-git-send-email-kamalesh@linux.vnet.ibm.com>
Message-ID: <14d7f3de-37f1-786c-e7e3-96d7f9c89bed@redhat.com>



On Friday 28 October 2016 10:37 AM, Kamalesh Babulal wrote:
> Kernel commit 7523e4dc50 (module: use a structure to encapsulate layout.)
> encapsulates core_layout and init_layout into module_layout structure.
>
> commit fa6a75a93 (Fix module core base and size offset for kernel v4.5)
> fixes offset value calculation for core layout's base and size, whereas
> Kernel v4.5 module changes also needs fixing of module init_size and
> module_init for the makedumpfile to read the correct module address.
>
> This patch fixes calculation of offsets values for module init_size and
> module_init.
>
> Signed-off-by: Kamalesh Babulal <kamalesh at linux.vnet.ibm.com>
> Cc: Pratyush Anand <panand at redhat.com>

Reviewed-by: Pratyush Anand <panand at redhat.com>

> ---
>  makedumpfile.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>
> diff --git a/makedumpfile.c b/makedumpfile.c
> index 853b999..f33a90d 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -1689,7 +1689,25 @@ get_structure_info(void)
>  		OFFSET(module.core_size) += core_layout;
>  	}
>  	OFFSET_INIT(module.module_init, "module", "module_init");
> +	if (OFFSET(module.module_init) == NOT_FOUND_STRUCTURE) {
> +		/* for kernel version 4.5 and above */
> +		long init_layout;
> +
> +		OFFSET_INIT(module.module_init, "module", "init_layout");
> +		init_layout = OFFSET(module.module_init);
> +		OFFSET_INIT(module.module_init, "module_layout", "base");
> +		OFFSET(module.module_init) += init_layout;
> +	}
>  	OFFSET_INIT(module.init_size, "module", "init_size");
> +	if (OFFSET(module.init_size) == NOT_FOUND_STRUCTURE) {
> +		/* for kernel version 4.5 and above */
> +		long init_layout;
> +
> +		OFFSET_INIT(module.init_size, "module", "init_layout");
> +		init_layout = OFFSET(module.init_size);
> +		OFFSET_INIT(module.init_size, "module_layout", "size");
> +		OFFSET(module.init_size) += init_layout;
> +	}
>
>  	ENUM_NUMBER_INIT(NR_FREE_PAGES, "NR_FREE_PAGES");
>  	ENUM_NUMBER_INIT(N_ONLINE, "N_ONLINE");
>


From ats-kumagai at wm.jp.nec.com  Thu Oct 27 23:36:51 2016
From: ats-kumagai at wm.jp.nec.com (Atsushi Kumagai)
Date: Fri, 28 Oct 2016 06:36:51 +0000
Subject: [PATCH] Fix module module_init/init_size offsets for v4.5 kernel
In-Reply-To: <14d7f3de-37f1-786c-e7e3-96d7f9c89bed@redhat.com>
References: <1477631234-15500-1-git-send-email-kamalesh@linux.vnet.ibm.com>
 <14d7f3de-37f1-786c-e7e3-96d7f9c89bed@redhat.com>
Message-ID: <0910DD04CBD6DE4193FCF86B9C00BE9701E7B213@BPXM01GP.gisp.nec.co.jp>

Hello Kamalesh and Pratyush,

>On Friday 28 October 2016 10:37 AM, Kamalesh Babulal wrote:
>> Kernel commit 7523e4dc50 (module: use a structure to encapsulate layout.)
>> encapsulates core_layout and init_layout into module_layout structure.
>>
>> commit fa6a75a93 (Fix module core base and size offset for kernel v4.5)
>> fixes offset value calculation for core layout's base and size, whereas
>> Kernel v4.5 module changes also needs fixing of module init_size and
>> module_init for the makedumpfile to read the correct module address.
>>
>> This patch fixes calculation of offsets values for module init_size and
>> module_init.
>>
>> Signed-off-by: Kamalesh Babulal <kamalesh at linux.vnet.ibm.com>
>> Cc: Pratyush Anand <panand at redhat.com>
>
>Reviewed-by: Pratyush Anand <panand at redhat.com>

Thanks, but I think Guenther posted the same fix which you can see
in the devel branch:

commit 32dd46803944959f78e01e7c4847c465efca99a6
Author: Guenther Hutzl <hutzl at linux.vnet.ibm.com>
Date:   Wed Jul 6 20:00:54 2016 +0900

    [PATCH] Fix module init base and size offset for kernel v4.5

    This is a follow-up patch on the patch provided in post:

    "[PATCH] makedumpfile: fix module core base and size offset for kernel v4.5"
    by Pratyush Anand


Thanks,
Atsushi Kumagai


>> ---
>>  makedumpfile.c | 18 ++++++++++++++++++
>>  1 file changed, 18 insertions(+)
>>
>> diff --git a/makedumpfile.c b/makedumpfile.c
>> index 853b999..f33a90d 100644
>> --- a/makedumpfile.c
>> +++ b/makedumpfile.c
>> @@ -1689,7 +1689,25 @@ get_structure_info(void)
>>  		OFFSET(module.core_size) += core_layout;
>>  	}
>>  	OFFSET_INIT(module.module_init, "module", "module_init");
>> +	if (OFFSET(module.module_init) == NOT_FOUND_STRUCTURE) {
>> +		/* for kernel version 4.5 and above */
>> +		long init_layout;
>> +
>> +		OFFSET_INIT(module.module_init, "module", "init_layout");
>> +		init_layout = OFFSET(module.module_init);
>> +		OFFSET_INIT(module.module_init, "module_layout", "base");
>> +		OFFSET(module.module_init) += init_layout;
>> +	}
>>  	OFFSET_INIT(module.init_size, "module", "init_size");
>> +	if (OFFSET(module.init_size) == NOT_FOUND_STRUCTURE) {
>> +		/* for kernel version 4.5 and above */
>> +		long init_layout;
>> +
>> +		OFFSET_INIT(module.init_size, "module", "init_layout");
>> +		init_layout = OFFSET(module.init_size);
>> +		OFFSET_INIT(module.init_size, "module_layout", "size");
>> +		OFFSET(module.init_size) += init_layout;
>> +	}
>>
>>  	ENUM_NUMBER_INIT(NR_FREE_PAGES, "NR_FREE_PAGES");
>>  	ENUM_NUMBER_INIT(N_ONLINE, "N_ONLINE");
>>
>
>_______________________________________________
>kexec mailing list
>kexec at lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/kexec


From kamalesh at linux.vnet.ibm.com  Fri Oct 28 05:17:08 2016
From: kamalesh at linux.vnet.ibm.com (Kamalesh Babulal)
Date: Fri, 28 Oct 2016 17:47:08 +0530
Subject: [PATCH] Fix module module_init/init_size offsets for v4.5 kernel
In-Reply-To: <0910DD04CBD6DE4193FCF86B9C00BE9701E7B213@BPXM01GP.gisp.nec.co.jp>
References: <1477631234-15500-1-git-send-email-kamalesh@linux.vnet.ibm.com>
 <14d7f3de-37f1-786c-e7e3-96d7f9c89bed@redhat.com>
 <0910DD04CBD6DE4193FCF86B9C00BE9701E7B213@BPXM01GP.gisp.nec.co.jp>
Message-ID: <d2442381-6e06-fba1-750d-560978df5a4f@linux.vnet.ibm.com>



On Friday 28 October 2016 12:06 PM, Atsushi Kumagai wrote:
>> >On Friday 28 October 2016 10:37 AM, Kamalesh Babulal wrote:
>>> >>Kernel commit 7523e4dc50 (module: use a structure to encapsulate layout.)
>>> >>encapsulates core_layout and init_layout into module_layout structure.
>>> >>
>>> >>commit fa6a75a93 (Fix module core base and size offset for kernel v4.5)
>>> >>fixes offset value calculation for core layout's base and size, whereas
>>> >>Kernel v4.5 module changes also needs fixing of module init_size and
>>> >>module_init for the makedumpfile to read the correct module address.
>>> >>
>>> >>This patch fixes calculation of offsets values for module init_size and
>>> >>module_init.
>>> >>
>>> >>Signed-off-by: Kamalesh Babulal<kamalesh at linux.vnet.ibm.com>
>>> >>Cc: Pratyush Anand<panand at redhat.com>
>> >
>> >Reviewed-by: Pratyush Anand<panand at redhat.com>
> Thanks, but I think Guenther posted the same fix which you can see
> in the devel branch:
>
> commit 32dd46803944959f78e01e7c4847c465efca99a6
> Author: Guenther Hutzl<hutzl at linux.vnet.ibm.com>
> Date:   Wed Jul 6 20:00:54 2016 +0900
>
>      [PATCH] Fix module init base and size offset for kernel v4.5

Thank you for pointing out the commit. Should I rebase future patch
against devel branch.

Thanks,
Kamalesh.



From geoff at infradead.org  Fri Oct 28 11:43:48 2016
From: geoff at infradead.org (Geoff Levand)
Date: Fri, 28 Oct 2016 11:43:48 -0700
Subject: [PATCH V2] arm64: Add support of R_AARCH64_PREL32 relocation in
 purgatory
In-Reply-To: <f970f7938109c40833fc45e3d6d72b1dcdf14595.1477627895.git.panand@redhat.com>
References: <f970f7938109c40833fc45e3d6d72b1dcdf14595.1477627895.git.panand@redhat.com>
Message-ID: <3175f823-dd03-07f6-fffe-6ec5487cbf93@infradead.org>

On 10/27/2016 09:16 PM, Pratyush Anand wrote:
> gcc version in fedora koji is  6.2.1-2.fc25. kexec-tools compiled with this
> gcc produced another relocation error:
> 
> machine_apply_elf_rel: ERROR Unknown type: 261
> 
> This patch fixes the above error.

Looks good.  Simon, please apply.

Reviewed-by: Geoff Levand <geoff at infradead.org>



From ats-kumagai at wm.jp.nec.com  Sun Oct 30 23:17:00 2016
From: ats-kumagai at wm.jp.nec.com (Atsushi Kumagai)
Date: Mon, 31 Oct 2016 06:17:00 +0000
Subject: [PATCH] Fix module module_init/init_size offsets for v4.5 kernel
In-Reply-To: <d2442381-6e06-fba1-750d-560978df5a4f@linux.vnet.ibm.com>
References: <1477631234-15500-1-git-send-email-kamalesh@linux.vnet.ibm.com>
 <14d7f3de-37f1-786c-e7e3-96d7f9c89bed@redhat.com>
 <0910DD04CBD6DE4193FCF86B9C00BE9701E7B213@BPXM01GP.gisp.nec.co.jp>
 <d2442381-6e06-fba1-750d-560978df5a4f@linux.vnet.ibm.com>
Message-ID: <0910DD04CBD6DE4193FCF86B9C00BE9701E7B73C@BPXM01GP.gisp.nec.co.jp>

>On Friday 28 October 2016 12:06 PM, Atsushi Kumagai wrote:
>>> >On Friday 28 October 2016 10:37 AM, Kamalesh Babulal wrote:
>>>> >>Kernel commit 7523e4dc50 (module: use a structure to encapsulate layout.)
>>>> >>encapsulates core_layout and init_layout into module_layout structure.
>>>> >>
>>>> >>commit fa6a75a93 (Fix module core base and size offset for kernel v4.5)
>>>> >>fixes offset value calculation for core layout's base and size, whereas
>>>> >>Kernel v4.5 module changes also needs fixing of module init_size and
>>>> >>module_init for the makedumpfile to read the correct module address.
>>>> >>
>>>> >>This patch fixes calculation of offsets values for module init_size and
>>>> >>module_init.
>>>> >>
>>>> >>Signed-off-by: Kamalesh Babulal<kamalesh at linux.vnet.ibm.com>
>>>> >>Cc: Pratyush Anand<panand at redhat.com>
>>> >
>>> >Reviewed-by: Pratyush Anand<panand at redhat.com>
>> Thanks, but I think Guenther posted the same fix which you can see
>> in the devel branch:
>>
>> commit 32dd46803944959f78e01e7c4847c465efca99a6
>> Author: Guenther Hutzl<hutzl at linux.vnet.ibm.com>
>> Date:   Wed Jul 6 20:00:54 2016 +0900
>>
>>      [PATCH] Fix module init base and size offset for kernel v4.5
>
>Thank you for pointing out the commit. Should I rebase future patch
>against devel branch.

Yes, I recommend that. It's better also for me to review.

Thanks,
Atsushi Kumagai


From panand at redhat.com  Mon Oct 31 01:17:34 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 31 Oct 2016 13:47:34 +0530
Subject: [Makedumpfile PATCH V2 1/4] x86_64: Calculate page_offset from pt_load
In-Reply-To: <cover.1477901442.git.panand@redhat.com>
References: <cover.1477901442.git.panand@redhat.com>
Message-ID: <f7d79453d0c009a2c215914e5956a85d9cb73280.1477901442.git.panand@redhat.com>

page_offset can always be calculated as 'virtual - physical' for a direct
mapping area on x86. Therefore, remove the version dependent calculation
and use this method.

Suggested-by: Baoquan He <bhe at redhat.com>
Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/x86_64.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/arch/x86_64.c b/arch/x86_64.c
index ddf7be6bc57b..eba725e41aac 100644
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -44,6 +44,24 @@ get_xen_p2m_mfn(void)
 	return NOT_FOUND_LONG_VALUE;
 }
 
+static int
+get_page_offset_x86_64(void)
+{
+	int i;
+	unsigned long long phys_start;
+	unsigned long long virt_start;
+
+	for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
+		if (virt_start < __START_KERNEL_map) {
+			info->page_offset = virt_start - phys_start;
+			return TRUE;
+		}
+	}
+
+	ERRMSG("Can't get any pt_load to calculate page offset.\n");
+	return FALSE;
+}
+
 int
 get_phys_base_x86_64(void)
 {
@@ -159,10 +177,8 @@ get_versiondep_info_x86_64(void)
 	else
 		info->max_physmem_bits  = _MAX_PHYSMEM_BITS_2_6_31;
 
-	if (info->kernel_version < KERNEL_VERSION(2, 6, 27))
-		info->page_offset = __PAGE_OFFSET_ORIG;
-	else
-		info->page_offset = __PAGE_OFFSET_2_6_27;
+	if (!get_page_offset_x86_64())
+		return FALSE;
 
 	if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
 		info->vmalloc_start = VMALLOC_START_ORIG;
-- 
2.7.4



From panand at redhat.com  Mon Oct 31 01:17:33 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 31 Oct 2016 13:47:33 +0530
Subject: [Makedumpfile PATCH V2 0/4] x86_64: Fix page_offset for randomized
 base enabled
Message-ID: <cover.1477901442.git.panand@redhat.com>

Patch 1/4 fixes page_offset calculation, so that it is correctly calculated
on KASLR enabled kernel as well.
Patch 2/4 simplifies VA to PA translation. New code has been benchmarked
against old code on a 4T system.
Patch 3/4 and 4/4 is removal of (now) unnecessary code.

I think, we should find a way to kill find_vememmap() as well, so that
VMEMMAP_START can be removed. I have very limited idea about x86, so unable
to do that as of now.

Changes since V1:
* A bug in patch 1/4 fixed
* Patch log of 2/4 improved to include more number of trials

Pratyush Anand (4):
  x86_64: Calculate page_offset from pt_load
  x86_64: translate all VA to PA using page table values
  x86_64: kill is_vmalloc_addr_x86_64()
  x86_64: kill some unused initialization

 arch/x86_64.c  | 84 ++++++++++++++++++++--------------------------------------
 makedumpfile.h |  9 +++----
 2 files changed, 32 insertions(+), 61 deletions(-)

-- 
2.7.4



From panand at redhat.com  Mon Oct 31 01:17:35 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 31 Oct 2016 13:47:35 +0530
Subject: [Makedumpfile PATCH V2 2/4] x86_64: translate all VA to PA using page
 table values
In-Reply-To: <cover.1477901442.git.panand@redhat.com>
References: <cover.1477901442.git.panand@redhat.com>
Message-ID: <c72c3722595f7b86754c6d9835ffdc3c68361bb4.1477901442.git.panand@redhat.com>

Currently we translate some of the VA areas using linear mapping while some
other(which can not be linearly mapped) using page table.

However, we will have entry of a page in the page table irrespective of its
virtual region. So, we can always look into page table for any VA to PA
translation. This approach will solve lot of complexity in makedumpfile. It
will in turn remove dependency over variables like VMALLOC_START,
MODULES_VADDR etc whose definition keeps changing in newer kernel version.

Moreover, I do not see any side effect of this approach in terms of
execution timing. I tested with IBM x3950 X6 machine having 4136359 MB of
memory with -d 1 option. In fact, over a 19+ trials, new code shows
slightly better result (2592 S) than upstream code (2652 S). These are the
results of makedumpfile execution time:

$ cat console.log | grep "makedumpfile execution time with upstream code
is"
makedumpfile execution time with upstream code is 2750.243266765
makedumpfile execution time with upstream code is 2772.954322748
makedumpfile execution time with upstream code is 2778.147847869
makedumpfile execution time with upstream code is 2668.136180424
makedumpfile execution time with upstream code is 2543.101660682
makedumpfile execution time with upstream code is 2757.314292073
makedumpfile execution time with upstream code is 2478.658846427
makedumpfile execution time with upstream code is 2745.728099825
makedumpfile execution time with upstream code is 2577.807602709
makedumpfile execution time with upstream code is 2548.787385748
makedumpfile execution time with upstream code is 2757.644602365
makedumpfile execution time with upstream code is 2562.336482019
makedumpfile execution time with upstream code is 2559.935682252
makedumpfile execution time with upstream code is 2546.670738446
makedumpfile execution time with upstream code is 2744.063245015
makedumpfile execution time with upstream code is 2744.243866098
makedumpfile execution time with upstream code is 2549.050846459
makedumpfile execution time with upstream code is 2759.081822434
makedumpfile execution time with upstream code is 2549.571317987
$ cat console.log | grep "makedumpfile execution time with upstream code
is" | cut -d ' ' -f 8 | awk -F : '{sum+=$1} END {print "AVG=",sum/NR}'
AVG= 2652.29

$ cat console.log | grep "makedumpfile execution time with new code is"
makedumpfile execution time with new code is 2534.312841588
makedumpfile execution time with new code is 2549.943691468
makedumpfile execution time with new code is 2562.056355355
makedumpfile execution time with new code is 2744.429671429
makedumpfile execution time with new code is 2536.959188162
makedumpfile execution time with new code is 2543.148060626
makedumpfile execution time with new code is 2548.634229064
makedumpfile execution time with new code is 2554.985669453
makedumpfile execution time with new code is 2756.479546003
makedumpfile execution time with new code is 2736.303174442
makedumpfile execution time with new code is 2564.855527093
makedumpfile execution time with new code is 2479.417937688
makedumpfile execution time with new code is 2555.431578921
makedumpfile execution time with new code is 2741.293207275
makedumpfile execution time with new code is 2745.547802440
makedumpfile execution time with new code is 2555.950078489
makedumpfile execution time with new code is 2558.421768940
makedumpfile execution time with new code is 2534.342072864
makedumpfile execution time with new code is 2542.824611652
makedumpfile execution time with new code is 2557.413054122
makedumpfile execution time with new code is 2553.609188082
makedumpfile execution time with new code is 2766.161683444
makedumpfile execution time with new code is 2571.997408197
makedumpfile execution time with new code is 2541.121903364
makedumpfile execution time with new code is 2472.805795262
$ cat console.log | grep "makedumpfile execution time with new code is" |
cut -d ' ' -f 8 | awk -F : '{sum+=$1} END {print "AVG=",sum/NR}'
AVG= 2592.34

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/x86_64.c  | 42 ++++++++----------------------------------
 makedumpfile.h |  4 ++--
 2 files changed, 10 insertions(+), 36 deletions(-)

diff --git a/arch/x86_64.c b/arch/x86_64.c
index eba725e41aac..9afa38fd141a 100644
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -203,6 +203,12 @@ vtop4_x86_64(unsigned long vaddr)
 {
 	unsigned long page_dir, pml4, pgd_paddr, pgd_pte, pmd_paddr, pmd_pte;
 	unsigned long pte_paddr, pte;
+	unsigned long phys_base;
+
+	if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
+		phys_base = info->phys_base;
+	else
+		phys_base = 0;
 
 	if (SYMBOL(init_level4_pgt) == NOT_FOUND_SYMBOL) {
 		ERRMSG("Can't get the symbol of init_level4_pgt.\n");
@@ -212,9 +218,9 @@ vtop4_x86_64(unsigned long vaddr)
 	/*
 	 * Get PGD.
 	 */
-	page_dir  = SYMBOL(init_level4_pgt);
+	page_dir = SYMBOL(init_level4_pgt) - __START_KERNEL_map + phys_base;
 	page_dir += pml4_index(vaddr) * sizeof(unsigned long);
-	if (!readmem(VADDR, page_dir, &pml4, sizeof pml4)) {
+	if (!readmem(PADDR, page_dir, &pml4, sizeof pml4)) {
 		ERRMSG("Can't get pml4 (page_dir:%lx).\n", page_dir);
 		return NOT_PADDR;
 	}
@@ -285,38 +291,6 @@ vtop4_x86_64(unsigned long vaddr)
 	return (pte & ENTRY_MASK) + PAGEOFFSET(vaddr);
 }
 
-unsigned long long
-vaddr_to_paddr_x86_64(unsigned long vaddr)
-{
-	unsigned long phys_base;
-	unsigned long long paddr;
-
-	/*
-	 * Check the relocatable kernel.
-	 */
-	if (SYMBOL(phys_base) != NOT_FOUND_SYMBOL)
-		phys_base = info->phys_base;
-	else
-		phys_base = 0;
-
-	if (is_vmalloc_addr_x86_64(vaddr)) {
-		if ((paddr = vtop4_x86_64(vaddr)) == NOT_PADDR) {
-			ERRMSG("Can't convert a virtual address(%lx) to " \
-			    "physical address.\n", vaddr);
-			return NOT_PADDR;
-		}
-	} else if (vaddr >= __START_KERNEL_map) {
-		paddr = vaddr - __START_KERNEL_map + phys_base;
-
-	} else {
-		if (is_xen_memory())
-			paddr = vaddr - PAGE_OFFSET_XEN_DOM0;
-		else
-			paddr = vaddr - PAGE_OFFSET;
-	}
-	return paddr;
-}
-
 /*
  * for Xen extraction
  */
diff --git a/makedumpfile.h b/makedumpfile.h
index a5955ff750e5..13559651feb6 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -863,12 +863,12 @@ int is_vmalloc_addr_x86_64(ulong vaddr);
 int get_phys_base_x86_64(void);
 int get_machdep_info_x86_64(void);
 int get_versiondep_info_x86_64(void);
-unsigned long long vaddr_to_paddr_x86_64(unsigned long vaddr);
+unsigned long long vtop4_x86_64(unsigned long vaddr);
 #define find_vmemmap()		find_vmemmap_x86_64()
 #define get_phys_base()		get_phys_base_x86_64()
 #define get_machdep_info()	get_machdep_info_x86_64()
 #define get_versiondep_info()	get_versiondep_info_x86_64()
-#define vaddr_to_paddr(X)	vaddr_to_paddr_x86_64(X)
+#define vaddr_to_paddr(X)	vtop4_x86_64(X)
 #define is_phys_addr(X)		(!is_vmalloc_addr_x86_64(X))
 #endif /* x86_64 */
 
-- 
2.7.4



From panand at redhat.com  Mon Oct 31 01:17:36 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 31 Oct 2016 13:47:36 +0530
Subject: [Makedumpfile PATCH V2 3/4] x86_64: kill is_vmalloc_addr_x86_64()
In-Reply-To: <cover.1477901442.git.panand@redhat.com>
References: <cover.1477901442.git.panand@redhat.com>
Message-ID: <e7e3f39e52323fb2387b48d7f8f9f561f893a144.1477901442.git.panand@redhat.com>

>From kernel documentation:
ffffffff80000000 - ffffffff9fffffff (=512 MB)  kernel text mapping, from phys 0
ffffffffa0000000 - ffffffffff5fffff (=1526 MB) module mapping space

So, it is only the module area which is lying above __START_KERNEL_map.
However, kexec-tools only creates PT_LOAD segments for kernel text region
and crash memory region. So, we can safely remove the check for
!is_vmalloc_addr_x86_64() from get_phys_base_x86_64().

Since, this was the last usage of is_vmalloc_addr_x86_64(), so kill it as
well.

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/x86_64.c  | 14 +-------------
 makedumpfile.h |  3 +--
 2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/arch/x86_64.c b/arch/x86_64.c
index 9afa38fd141a..9e2940ca75d9 100644
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -21,17 +21,6 @@
 extern struct vmap_pfns *gvmem_pfns;
 extern int nr_gvmem_pfns;
 
-int
-is_vmalloc_addr_x86_64(ulong vaddr)
-{
-	/*
-	 *  vmalloc, virtual memmap, and module space as VMALLOC space.
-	 */
-	return ((vaddr >= VMALLOC_START && vaddr <= VMALLOC_END)
-	    || (vaddr >= VMEMMAP_START && vaddr <= VMEMMAP_END)
-	    || (vaddr >= MODULES_VADDR && vaddr <= MODULES_END));
-}
-
 static unsigned long
 get_xen_p2m_mfn(void)
 {
@@ -75,8 +64,7 @@ get_phys_base_x86_64(void)
 	info->phys_base = 0; /* default/traditional */
 
 	for (i = 0; get_pt_load(i, &phys_start, NULL, &virt_start, NULL); i++) {
-		if ((virt_start >= __START_KERNEL_map) &&
-		    !(is_vmalloc_addr_x86_64(virt_start))) {
+		if (virt_start >= __START_KERNEL_map) {
 
 			info->phys_base = phys_start -
 			    (virt_start & ~(__START_KERNEL_map));
diff --git a/makedumpfile.h b/makedumpfile.h
index 13559651feb6..8a96da1f61bd 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -859,7 +859,6 @@ unsigned long long vaddr_to_paddr_x86(unsigned long vaddr);
 #endif /* x86 */
 
 #ifdef __x86_64__
-int is_vmalloc_addr_x86_64(ulong vaddr);
 int get_phys_base_x86_64(void);
 int get_machdep_info_x86_64(void);
 int get_versiondep_info_x86_64(void);
@@ -869,7 +868,7 @@ unsigned long long vtop4_x86_64(unsigned long vaddr);
 #define get_machdep_info()	get_machdep_info_x86_64()
 #define get_versiondep_info()	get_versiondep_info_x86_64()
 #define vaddr_to_paddr(X)	vtop4_x86_64(X)
-#define is_phys_addr(X)		(!is_vmalloc_addr_x86_64(X))
+#define is_phys_addr(X)		stub_true_ul(X)
 #endif /* x86_64 */
 
 #ifdef __powerpc64__ /* powerpc64 */
-- 
2.7.4



From panand at redhat.com  Mon Oct 31 01:17:37 2016
From: panand at redhat.com (Pratyush Anand)
Date: Mon, 31 Oct 2016 13:47:37 +0530
Subject: [Makedumpfile PATCH V2 4/4] x86_64: kill some unused initialization
In-Reply-To: <cover.1477901442.git.panand@redhat.com>
References: <cover.1477901442.git.panand@redhat.com>
Message-ID: <98d8c98aeacec06f2276149da989a631cd5935d8.1477901442.git.panand@redhat.com>

VMALLOC_START, VMALLOC_END, MODULES_VADDR and MODULES_END are mo more
needed for x86_64 now. So, kill their initialization.

Signed-off-by: Pratyush Anand <panand at redhat.com>
---
 arch/x86_64.c  | 4 ----
 makedumpfile.h | 2 --
 2 files changed, 6 deletions(-)

diff --git a/arch/x86_64.c b/arch/x86_64.c
index 9e2940ca75d9..3ef33ae4ef2d 100644
--- a/arch/x86_64.c
+++ b/arch/x86_64.c
@@ -169,13 +169,9 @@ get_versiondep_info_x86_64(void)
 		return FALSE;
 
 	if (info->kernel_version < KERNEL_VERSION(2, 6, 31)) {
-		info->vmalloc_start = VMALLOC_START_ORIG;
-		info->vmalloc_end   = VMALLOC_END_ORIG;
 		info->vmemmap_start = VMEMMAP_START_ORIG;
 		info->vmemmap_end   = VMEMMAP_END_ORIG;
 	} else {
-		info->vmalloc_start = VMALLOC_START_2_6_31;
-		info->vmalloc_end   = VMALLOC_END_2_6_31;
 		info->vmemmap_start = VMEMMAP_START_2_6_31;
 		info->vmemmap_end   = VMEMMAP_END_2_6_31;
 	}
diff --git a/makedumpfile.h b/makedumpfile.h
index 8a96da1f61bd..338c651388f0 100644
--- a/makedumpfile.h
+++ b/makedumpfile.h
@@ -575,8 +575,6 @@ int get_va_bits_arm64(void);
 #define __START_KERNEL_map	(0xffffffff80000000)
 #define KERNEL_IMAGE_SIZE_ORIG		(0x0000000008000000) /* 2.6.25, or former */
 #define KERNEL_IMAGE_SIZE_2_6_26	(0x0000000020000000) /* 2.6.26, or later  */
-#define MODULES_VADDR          (__START_KERNEL_map + NUMBER(KERNEL_IMAGE_SIZE))
-#define MODULES_END		(0xfffffffffff00000)
 #define KVBASE			PAGE_OFFSET
 #define _SECTION_SIZE_BITS	(27)
 #define _MAX_PHYSMEM_BITS_ORIG		(40)
-- 
2.7.4



From takahiro.akashi at linaro.org  Mon Oct 31 01:50:09 2016
From: takahiro.akashi at linaro.org (AKASHI Takahiro)
Date: Mon, 31 Oct 2016 17:50:09 +0900
Subject: Memory range end be inclusive or exclusive? Re: [PATCH v1 1/4]
 kexec: (bugfix) calc correct end address of memory ranges in device tree
In-Reply-To: <20160906002958.GB16712@linaro.org>
References: <cover.1468970114.git.geoff@infradead.org>
 <3562841.ROYbCgkeeq@hactar>
 <20160727232331.GY1041@n2100.armlinux.org.uk>
 <1860371.lT9GInp2C3@hactar>
 <20160729082714.GA1041@n2100.armlinux.org.uk>
 <1469812346.16559.40.camel@infradead.org>
 <20160729172356.GD1041@n2100.armlinux.org.uk>
 <20160801045240.GD7995@linaro.org>
 <20160906002958.GB16712@linaro.org>
Message-ID: <20161031085008.GF19531@linaro.org>

Simon,

On Tue, Sep 06, 2016 at 09:29:59AM +0900, AKASHI Takahiro wrote:
> Simon,
> 
> What is your opinion on this issue?

Pinged you several times so far.

Can you please give me your comment?
(attached below is the original patch.)

-Takahiro AKASHI

> 
> On Mon, Aug 01, 2016 at 01:52:40PM +0900, AKASHI Takahiro wrote:
> > On Fri, Jul 29, 2016 at 06:23:56PM +0100, Russell King - ARM Linux wrote:
> > > On Fri, Jul 29, 2016 at 10:12:26AM -0700, Geoff Levand wrote:
> > > > On Fri, 2016-07-29 at 09:27 +0100, Russell King - ARM Linux wrote:
> > > > 
> > > > > So, these functions are a mess and need fixing.
> > > > 
> > > > Since this change isn't really related to arm64 support, I'll
> > > > drop this patch from my series.
> > > 
> > > Do you have a case which triggers bugs in this code?
> > 
> > Actually, this patch was necessary when my kdump used "usable-memory"
> > properties in "memory" nodes, as on ppc64, to limit the usable memory
> > regions that can be used by crash dump kernel.
> > Since then, I've moved to the approach of using "mem=" kernel parameter,
> > then introducing a new property, "linux,usable-memory-range," under /chosen
> > and now we don't need this patch any more.
> > 
> > So, we can drop it but I still believe that it is buggy.
> 
> Due to the discussions[1], I may want to re-enable "usable-memory"
> property on arm64. In addition, I would like to add a function,
> dtb_add_usable_memory_properties(), a variant of
> add_usable_memory_properties(), to kexec/dt-ops.c.
> So this issue is quite crucial now.
> 
> [1] http://lists.infradead.org/pipermail/linux-arm-kernel/2016-August/452685.html
> 
> -Takahiro AKASHI
> 
> > Thanks,
> > -Takahiro AKASHI
> > 
> > > -- 
> > > RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> > > FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
> > > according to speedtest.net.
===8<===
From: AKASHI Takahiro <takahiro.akashi at linaro.org>

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 79aa0f3..953f78a 100644
--- a/kexec/fs2dt.c
+++ b/kexec/fs2dt.c
@@ -236,7 +236,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++;
 			}
 		}
@@ -350,7 +351,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.10.0



From sgoel at codeaurora.org  Mon Oct 31 12:11:08 2016
From: sgoel at codeaurora.org (Goel, Sameer)
Date: Mon, 31 Oct 2016 13:11:08 -0600
Subject: [PATCH] kexec: Increase the upper limit for RAM segments
In-Reply-To: <cad5f084-b914-f522-eb43-71ed8a45b2a0@infradead.org>
References: <1477005268-26943-1-git-send-email-sgoel@codeaurora.org>
 <cad5f084-b914-f522-eb43-71ed8a45b2a0@infradead.org>
Message-ID: <43d2add1-15f5-7e62-b8ce-9a8afeff71f3@codeaurora.org>

This change is needed in case when the System Ram listings are retrieved 
from /proc/iomem. On a newer UEFI based Qualcomm system, the number of 
regions listed were close to 34. So, the actual system ram region was 
not covered and the kexec tool failed to load the kernel image.

So, I have requested an increase in the number of memory regions.
Thanks,
Sameer

On 10/21/2016 11:05 AM, Geoff Levand wrote:
> Hi Sameer.
>
> On 10/20/2016 04:14 PM, Sameer Goel wrote:
>> Change the current hardcoded values to 64 from 16.
>
> Please add an explanation of why this change is needed.
>
> -Geoff
>
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
>

-- 
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.


From bhe at redhat.com  Mon Oct 31 18:37:14 2016
From: bhe at redhat.com (Baoquan He)
Date: Tue, 1 Nov 2016 09:37:14 +0800
Subject: [PATCH] kexec: Increase the upper limit for RAM segments
In-Reply-To: <43d2add1-15f5-7e62-b8ce-9a8afeff71f3@codeaurora.org>
References: <1477005268-26943-1-git-send-email-sgoel@codeaurora.org>
 <cad5f084-b914-f522-eb43-71ed8a45b2a0@infradead.org>
 <43d2add1-15f5-7e62-b8ce-9a8afeff71f3@codeaurora.org>
Message-ID: <20161101013714.GA20838@x1>

On 10/31/16 at 01:11pm, Goel, Sameer wrote:
> This change is needed in case when the System Ram listings are retrieved
> from /proc/iomem. On a newer UEFI based Qualcomm system, the number of
> regions listed were close to 34. So, the actual system ram region was not
> covered and the kexec tool failed to load the kernel image.
> 
> So, I have requested an increase in the number of memory regions.
> Thanks,

It would be great to add this to your patch log so that reviewers can
understand it better. Better repost with an updated patch log, copying
these as patch log is good enough.

> Sameer
> 
> On 10/21/2016 11:05 AM, Geoff Levand wrote:
> > Hi Sameer.
> > 
> > On 10/20/2016 04:14 PM, Sameer Goel wrote:
> > > Change the current hardcoded values to 64 from 16.
> > 
> > Please add an explanation of why this change is needed.
> > 
> > -Geoff
> > 
> > _______________________________________________
> > kexec mailing list
> > kexec at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/kexec
> > 
> 
> -- 
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project.
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From dyoung at redhat.com  Mon Oct 31 22:10:19 2016
From: dyoung at redhat.com (Dave Young)
Date: Tue, 1 Nov 2016 13:10:19 +0800
Subject: [PATCH] kexec: Export memory sections virtual addresses to
 vmcoreinfo
In-Reply-To: <1475743561-23912-1-git-send-email-bhe@redhat.com>
References: <1475743561-23912-1-git-send-email-bhe@redhat.com>
Message-ID: <20161101051019.GB4625@dhcp-128-65.nay.redhat.com>

On 10/06/16 at 04:46pm, Baoquan He wrote:
> KASLR memory randomization can randomize the base of the physical memory
> mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap
> (VMEMMAP_START). These need be exported to VMCOREINFO so that user space
> utility, mainly makedumpfile can use them to identify the base of each
> memory section. Here using VMCOREINFO_NUMBER we can reuse the existing
> struct number_table in makedumpfile to import data easily.
> 
> Since they are related to x86_64 only, put them into
> arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE
> together since it's also for x86_64 only.
> 
> Signed-off-by: Baoquan He <bhe at redhat.com>
> ---
>  arch/x86/kernel/machine_kexec_64.c | 4 ++++
>  kernel/kexec_core.c                | 3 ---
>  2 files changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
> index 5a294e4..e150dd7 100644
> --- a/arch/x86/kernel/machine_kexec_64.c
> +++ b/arch/x86/kernel/machine_kexec_64.c
> @@ -337,6 +337,10 @@ void arch_crash_save_vmcoreinfo(void)
>  #endif
>  	vmcoreinfo_append_str("KERNELOFFSET=%lx\n",
>  			      kaslr_offset());
> +	VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE);
> +	VMCOREINFO_NUMBER(PAGE_OFFSET);
> +	VMCOREINFO_NUMBER(VMALLOC_START);
> +	VMCOREINFO_NUMBER(VMEMMAP_START);

Pratyush has posted makedumpfile patches below to avoid the VMCOREINFO:
http://lists.infradead.org/pipermail/kexec/2016-October/017540.html

But we have this in mainline which also introduced the VMCOREINFO
numbers, can you send a patch to revert them?
commit 0549a3c02efb350776bc869685a361045efd3a29
Author: Thomas Garnier <thgarnie at google.com>
Date:   Tue Oct 11 13:55:08 2016 -0700

    kdump, vmcoreinfo: report memory sections virtual addresses
[snip]]

>  }
>  
>  /* arch-dependent functionality related to kexec file-based syscall */
> diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
> index 5616755..8ad3a29e 100644
> --- a/kernel/kexec_core.c
> +++ b/kernel/kexec_core.c
> @@ -1467,9 +1467,6 @@ static int __init crash_save_vmcoreinfo_init(void)
>  #endif
>  	VMCOREINFO_NUMBER(PG_head_mask);
>  	VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE);
> -#ifdef CONFIG_X86
> -	VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE);
> -#endif

Moving KERNEL_IMAGE_SIZE to x86 should be a standalone patch.
I remember Dave Anderson said he use it in crash utility, cced him.

>  #ifdef CONFIG_HUGETLB_PAGE
>  	VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR);
>  #endif
> -- 
> 2.5.5
> 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec

Thanks
Dave


From bhe at redhat.com  Mon Oct 31 22:33:53 2016
From: bhe at redhat.com (Baoquan He)
Date: Tue, 1 Nov 2016 13:33:53 +0800
Subject: [PATCH] kexec: Export memory sections virtual addresses to
 vmcoreinfo
In-Reply-To: <20161101051019.GB4625@dhcp-128-65.nay.redhat.com>
References: <1475743561-23912-1-git-send-email-bhe@redhat.com>
 <20161101051019.GB4625@dhcp-128-65.nay.redhat.com>
Message-ID: <20161101053353.GC20838@x1>

On 11/01/16 at 01:10pm, Dave Young wrote:
> On 10/06/16 at 04:46pm, Baoquan He wrote:
> > KASLR memory randomization can randomize the base of the physical memory
> > mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap
> > (VMEMMAP_START). These need be exported to VMCOREINFO so that user space
> > utility, mainly makedumpfile can use them to identify the base of each
> > memory section. Here using VMCOREINFO_NUMBER we can reuse the existing
> > struct number_table in makedumpfile to import data easily.
> > 
> > Since they are related to x86_64 only, put them into
> > arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE
> > together since it's also for x86_64 only.
> > 
> > Signed-off-by: Baoquan He <bhe at redhat.com>
> > ---
> >  arch/x86/kernel/machine_kexec_64.c | 4 ++++
> >  kernel/kexec_core.c                | 3 ---
> >  2 files changed, 4 insertions(+), 3 deletions(-)
> > 
> > diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
> > index 5a294e4..e150dd7 100644
> > --- a/arch/x86/kernel/machine_kexec_64.c
> > +++ b/arch/x86/kernel/machine_kexec_64.c
> > @@ -337,6 +337,10 @@ void arch_crash_save_vmcoreinfo(void)
> >  #endif
> >  	vmcoreinfo_append_str("KERNELOFFSET=%lx\n",
> >  			      kaslr_offset());
> > +	VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE);
> > +	VMCOREINFO_NUMBER(PAGE_OFFSET);
> > +	VMCOREINFO_NUMBER(VMALLOC_START);
> > +	VMCOREINFO_NUMBER(VMEMMAP_START);
> 
> Pratyush has posted makedumpfile patches below to avoid the VMCOREINFO:
> http://lists.infradead.org/pipermail/kexec/2016-October/017540.html
> 
> But we have this in mainline which also introduced the VMCOREINFO
> numbers, can you send a patch to revert them?

OK, will do.

However for find_vmemmap_x86_64() in makedumpfile, vmemmap_start is
still needed. I checked code, seems no better way to avoid. I am not
sure how many people are really using "-e" option to exclude unused
vmemmap pages.

Maybe just leave it as is, and fix it when people complain?

> commit 0549a3c02efb350776bc869685a361045efd3a29
> Author: Thomas Garnier <thgarnie at google.com>
> Date:   Tue Oct 11 13:55:08 2016 -0700
> 
>     kdump, vmcoreinfo: report memory sections virtual addresses
> [snip]]
> 
> >  }
> >  
> >  /* arch-dependent functionality related to kexec file-based syscall */
> > diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
> > index 5616755..8ad3a29e 100644
> > --- a/kernel/kexec_core.c
> > +++ b/kernel/kexec_core.c
> > @@ -1467,9 +1467,6 @@ static int __init crash_save_vmcoreinfo_init(void)
> >  #endif
> >  	VMCOREINFO_NUMBER(PG_head_mask);
> >  	VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE);
> > -#ifdef CONFIG_X86
> > -	VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE);
> > -#endif
> 
> Moving KERNEL_IMAGE_SIZE to x86 should be a standalone patch.
> I remember Dave Anderson said he use it in crash utility, cced him.
> 
> >  #ifdef CONFIG_HUGETLB_PAGE
> >  	VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR);
> >  #endif
> > -- 
> > 2.5.5
> > 
> > 
> > _______________________________________________
> > kexec mailing list
> > kexec at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/kexec
> 
> Thanks
> Dave


From dyoung at redhat.com  Mon Oct 31 22:34:11 2016
From: dyoung at redhat.com (Dave Young)
Date: Tue, 1 Nov 2016 13:34:11 +0800
Subject: [Makedumpfile PATCH V2 0/4] x86_64: Fix page_offset for
 randomized base enabled
In-Reply-To: <cover.1477901442.git.panand@redhat.com>
References: <cover.1477901442.git.panand@redhat.com>
Message-ID: <20161101053411.GA4952@dhcp-128-65.nay.redhat.com>

Pratyush, the patches works for me, thanks~

On 10/31/16 at 01:47pm, Pratyush Anand wrote:
> Patch 1/4 fixes page_offset calculation, so that it is correctly calculated
> on KASLR enabled kernel as well.
> Patch 2/4 simplifies VA to PA translation. New code has been benchmarked
> against old code on a 4T system.
> Patch 3/4 and 4/4 is removal of (now) unnecessary code.
> 
> I think, we should find a way to kill find_vememmap() as well, so that
> VMEMMAP_START can be removed. I have very limited idea about x86, so unable
> to do that as of now.

It was introduced in below commit, ccing Cliff Wickman, see if he has
thoughts.

commit 46176a97f329904c10d4efe5582594d55a04339c
Author: Cliff Wickman <cpw at sgi.com>
Date:   Mon Oct 26 23:20:18 2015 +0900

> 
> Changes since V1:
> * A bug in patch 1/4 fixed
> * Patch log of 2/4 improved to include more number of trials
> 
> Pratyush Anand (4):
>   x86_64: Calculate page_offset from pt_load
>   x86_64: translate all VA to PA using page table values
>   x86_64: kill is_vmalloc_addr_x86_64()
>   x86_64: kill some unused initialization
> 
>  arch/x86_64.c  | 84 ++++++++++++++++++++--------------------------------------
>  makedumpfile.h |  9 +++----
>  2 files changed, 32 insertions(+), 61 deletions(-)
> 
> -- 
> 2.7.4
> 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


