From d.hatayama at jp.fujitsu.com  Sun Sep  2 22:13:35 2012
From: d.hatayama at jp.fujitsu.com (HATAYAMA Daisuke)
Date: Mon, 03 Sep 2012 11:13:35 +0900 (JST)
Subject: [PATCH 03/16] [PATCH v3 3/12] Change the function related to
 excluding unnecessary pages.
In-Reply-To: <20120830164701.b64acec40a0bc1bac9b3457e@mxc.nes.nec.co.jp>
References: <20120830164422.8d05cbcdd650398d5d5cbad9@mxc.nes.nec.co.jp>
 <20120830164701.b64acec40a0bc1bac9b3457e@mxc.nes.nec.co.jp>
Message-ID: <20120903.111335.108627870.d.hatayama@jp.fujitsu.com>

From: Atsushi Kumagai <kumagai-atsushi at mxc.nes.nec.co.jp>
Subject: [PATCH 03/16] [PATCH v3 3/12] Change the function related to excluding unnecessary pages.
Date: Thu, 30 Aug 2012 16:47:01 +0900

> From: Atsushi Kumagai <kumagai-atsushi at mxc.nes.nec.co.jp>
> Date: Thu, 23 Aug 2012 17:49:16 +0900
> Subject: [PATCH 03/16] [PATCH v3 3/12] Change the function related to excluding unnecessary pages.
<cut>
> +int
> +exclude_unnecessary_pages_cyclic(void)
> +{
> +	unsigned int mm;
> +	struct mem_map_data *mmd;
> +
> +	/*
> +	 * Copy 1st-bitmap to 2nd-bitmap.
> +	 */
> +	copy_bitmap_cyclic();
> +
> +	if (info->dump_level & DL_EXCLUDE_FREE)
> +		if (!exclude_free_page())
> +			return FALSE;
> +
> +	/*
> +	 * Exclude cache pages, cache private pages, user data pages, and free pages.
> +	 */
> +	if (info->dump_level & DL_EXCLUDE_CACHE ||
> +	    info->dump_level & DL_EXCLUDE_CACHE_PRI ||
> +	    info->dump_level & DL_EXCLUDE_USER_DATA) {
> +		for (mm = 0; mm < info->num_mem_map; mm++) {
> +
> +			mmd = &info->mem_map_data[mm];
> +
> +			if (mmd->mem_map == NOT_MEMMAP_ADDR)
> +				continue;
> +
> +			if (mmd->pfn_end >= info->cyclic_start_pfn || mmd->pfn_start <= info->cyclic_end_pfn) {
> +				if (!__exclude_unnecessary_pages(mmd->mem_map,
> +								 mmd->pfn_start, mmd->pfn_end))
> +					return FALSE;
> +			}
> +		}
> +	}

This patch misses reporting the time consumed for excluding necessary
pages. I noticed this during benchmarking. Here is the patch I used at
the time, but I wrote this version over your patch set.

    Report the time consumed for excluding unnecessary pages in cyclic mode

    Here is the example:

    [Before]
    STEP [Excluding free pages       ] : 0.500269 seconds
    STEP [Excluding free pages       ] : 0.002081 seconds
    STEP [Copying data               ] : 2.115097 seconds

    [After]

    STEP [Excluding free pages       ] : 0.002148 seconds
    STEP [Excluding unnecessary pages] : 0.015641 seconds
    STEP [Excluding free pages       ] : 0.002130 seconds
    STEP [Excluding unnecessary pages] : 0.024436 seconds
    STEP [Copying data               ] : 0.211287 seconds

diff --git a/makedumpfile.c b/makedumpfile.c
index 0a43181..caac37b 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -3882,6 +3882,7 @@ exclude_unnecessary_pages_cyclic(void)
 {
        unsigned int mm;
        struct mem_map_data *mmd;
+       struct timeval tv_start;

        /*
         * Copy 1st-bitmap to 2nd-bitmap.
@@ -3898,8 +3899,13 @@ exclude_unnecessary_pages_cyclic(void)
        if (info->dump_level & DL_EXCLUDE_CACHE ||
            info->dump_level & DL_EXCLUDE_CACHE_PRI ||
            info->dump_level & DL_EXCLUDE_USER_DATA) {
+
+               gettimeofday(&tv_start, NULL);
+
                for (mm = 0; mm < info->num_mem_map; mm++) {

+                       print_progress(PROGRESS_UNN_PAGES, mm, info->num_mem_map);
+
                        mmd = &info->mem_map_data[mm];

                        if (mmd->mem_map == NOT_MEMMAP_ADDR)
@@ -3911,6 +3917,12 @@ exclude_unnecessary_pages_cyclic(void)
                                        return FALSE;
                        }
                }
+
+               /*
+                * print [100 %]
+                */
+               print_progress(PROGRESS_UNN_PAGES, info->num_mem_map, info->num_mem_map);
+               print_execution_time(PROGRESS_UNN_PAGES, &tv_start);
        }

        return TRUE;

Thanks.
HATAYAMA, Daisuke



From d.hatayama at jp.fujitsu.com  Sun Sep  2 22:50:57 2012
From: d.hatayama at jp.fujitsu.com (HATAYAMA Daisuke)
Date: Mon, 03 Sep 2012 11:50:57 +0900 (JST)
Subject: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep
 memory usage constant.
In-Reply-To: <20120830164521.0b07c16fe2993dd8afafc79b@mxc.nes.nec.co.jp>
References: <20120830164422.8d05cbcdd650398d5d5cbad9@mxc.nes.nec.co.jp>
 <20120830164521.0b07c16fe2993dd8afafc79b@mxc.nes.nec.co.jp>
Message-ID: <20120903.115057.275187572.d.hatayama@jp.fujitsu.com>

From: Atsushi Kumagai <kumagai-atsushi at mxc.nes.nec.co.jp>
Subject: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep memory usage constant.
Date: Thu, 30 Aug 2012 16:45:21 +0900

<cut>

> diff --git a/makedumpfile.c b/makedumpfile.c
> index d024e95..21bb55a 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -2553,6 +2553,8 @@ initial(void)
>  							info->name_memory);
>  			return FALSE;
>  		}
> +		info->flag_cyclic = FALSE;
> +

Please disable cyclic mode on sadump dumpfiles, too.


    sadump: Disable cyclic mode on sadump dumpfiles

    Signed-off-by: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>

diff --git a/makedumpfile.c b/makedumpfile.c
index 0a43181..9f5e8ed 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -2587,6 +2587,8 @@ initial(void)
                        return FALSE;
                }

+               info->flag_cyclic = FALSE;
+
                set_page_size(sadump_page_size());

                if (!sadump_initialize_bitmap_memory())


Thanks.
HATAYAMA, Daisuke



From d.hatayama at jp.fujitsu.com  Sun Sep  2 23:16:37 2012
From: d.hatayama at jp.fujitsu.com (HATAYAMA Daisuke)
Date: Mon, 03 Sep 2012 12:16:37 +0900 (JST)
Subject: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep
 memory usage constant.
In-Reply-To: <20120903.115057.275187572.d.hatayama@jp.fujitsu.com>
References: <20120830164422.8d05cbcdd650398d5d5cbad9@mxc.nes.nec.co.jp>
 <20120830164521.0b07c16fe2993dd8afafc79b@mxc.nes.nec.co.jp>
 <20120903.115057.275187572.d.hatayama@jp.fujitsu.com>
Message-ID: <20120903.121637.204037088.d.hatayama@jp.fujitsu.com>

From: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>
Subject: Re: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep memory usage constant.
Date: Mon, 3 Sep 2012 11:50:57 +0900

> From: Atsushi Kumagai <kumagai-atsushi at mxc.nes.nec.co.jp>
> Subject: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep memory usage constant.
> Date: Thu, 30 Aug 2012 16:45:21 +0900
> 
> <cut>
> 
>> diff --git a/makedumpfile.c b/makedumpfile.c
>> index d024e95..21bb55a 100644
>> --- a/makedumpfile.c
>> +++ b/makedumpfile.c
>> @@ -2553,6 +2553,8 @@ initial(void)
>>  							info->name_memory);
>>  			return FALSE;
>>  		}
>> +		info->flag_cyclic = FALSE;
>> +
> 
> Please disable cyclic mode on sadump dumpfiles, too.
> 

Also, there's no information to users about disabling cyclic mode.
Now switching from cyclic to normal mode is implicitly done. This is
confusing. I think some message indicating that, is necessary.

Thanks.
HATAYAMA, Daisuke



From kumagai-atsushi at mxc.nes.nec.co.jp  Sun Sep  2 23:42:33 2012
From: kumagai-atsushi at mxc.nes.nec.co.jp (Atsushi Kumagai)
Date: Mon, 3 Sep 2012 12:42:33 +0900
Subject: [PATCH] makedumpfile: keep dumpfile pages in a cache
In-Reply-To: <201208281949.50286.ptesarik@suse.cz>
References: <201208281949.50286.ptesarik@suse.cz>
Message-ID: <20120903124233.61eafa52ffaed6a38a23710d@mxc.nes.nec.co.jp>

Hello Petr,

On Tue, 28 Aug 2012 19:49:49 +0200
Petr Tesarik <ptesarik at suse.cz> wrote:

> Add a simple cache for pages read from the dumpfile.
> 
> This is a big win if we read consecutive data from one page, e.g.
> page descriptors, or even page table entries.
> 
> Note that makedumpfile now always reads a complete page. This was already
> the case with kdump-compressed and sadump formats, but makedumpfile was
> throwing most of the data away. For the kdump-compressed case, we may
> actually save a lot of decompression, too.
> 
> I tried to keep the cache small to minimize memory footprint, but it should
> be big enough to hold all pages to do 4-level paging plus some data. This
> is needed e.g. for vmalloc areas or Xen page frame table data, which are not
> contiguous in physical memory.
> 
> Signed-off-by: Petr Tesarik <ptesarik at suse.cz>

It's interesting to me. I want to know how performance will be improved
with this patch, so do you have speed measurements ?


Thanks
Atsushi Kumagai


From kumagai-atsushi at mxc.nes.nec.co.jp  Mon Sep  3 01:01:00 2012
From: kumagai-atsushi at mxc.nes.nec.co.jp (Atsushi Kumagai)
Date: Mon, 3 Sep 2012 14:01:00 +0900
Subject: [PATCHv3 0/9] Support Xen versions up to xen-4.1
In-Reply-To: <0E9227E8EFCFF54EA493F6C0399C015D39BFC5A112@ABGEX70E.FSC.NET>
References: <201208241741.27573.petr@tesarici.cz>
 <0E9227E8EFCFF54EA493F6C0399C015D39BFC5A112@ABGEX70E.FSC.NET>
Message-ID: <20120903140100.ac4dbf21401ace0e24a442d9@mxc.nes.nec.co.jp>

Hello Norbert and Petr,

On Fri, 31 Aug 2012 17:05:01 +0200
"Trapp, Norbert" <norbert.trapp at ts.fujitsu.com> wrote:

> 
> > -----Original Message-----
> > From: Petr Tesa??k [mailto:petr at tesarici.cz]
> > Sent: Friday, August 24, 2012 5:41 PM
> > To: kexec at lists.infradead.org
> > Cc: Trapp, Norbert
> > Subject: [PATCHv3 0/9] Support Xen versions up to xen-4.1
> > 
> > Hello everybody,
> > 
> > this is version 3 of my patch set. I'm very much indebted to Norbert
> > Trapp for his extensive testing of my previous patch set, which
> > revealed that Xen hypervisor static data was not kept with the previous
> > version of the patch set.
> > 
> > I could also add the performance improvements, but I'm afraid it would
> > make for an incremental patch, so let's wait until the filtering is
> > finally right.
> > 
> > I have re-tested this patch set with the same result as v2:
> > 
> >   - Xen-3.2.3 - WORKS
> >   - Xen-4.0.1 - WORKS (only with --xen-syms)
> >   - Xen-4.0.2 - WORKS
> >   - Xen-4.1.2 - WORKS
> > 
> > Filtering free pages (-d16 and above) doesn't work (even after I manually
> > provided the missing "max_pfn" symbol), but that seems unrelated, so I'm
> > going to address it in a subsequent patch set.
> > 
> > Norbert, if you test these patches, please send your comments to the
> > mailing list.
> 
> Hello Petr et al.,
> 
> after testing Petr's patches PATCHv3 plus "support for x86_64 1GB pages",
> "add missing return statement" and "keep dumpfile pages in a cache" on a
> machine with Xen 4.0.3 and 1GB pages there is only one comment I have:
> It all worked nicely!

Thank you for your report, that's good.
So, I'll review these patches for makedumpfile-1.5.1.


Thanks
Atsushi Kumagai

> With kind regards,
> 
> 	Norbert
> 
> Norbert Trapp
> PBG PDG ES&S SWE OS 6
> 
> FUJITSU
> Fujitsu Technology Solutions GmbH
> Domagkstra?e 28, D-80807 M?nchen, Germany
> E-mail: Norbert.Trapp at ts.fujitsu.com
> Web: ts.fujitsu.com
> Company details: ts.fujitsu.com/imprint
>  
> > Atsushi-san, if the patch set passes Norbert's testing, what else do you
> > need to accept the changes in upstream?
> > 
> > Regards,
> > Petr Tesarik
> > SUSE Linux
> > 
> 
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From ptesarik at suse.cz  Mon Sep  3 03:04:03 2012
From: ptesarik at suse.cz (Petr Tesarik)
Date: Mon, 3 Sep 2012 09:04:03 +0200
Subject: [PATCH] makedumpfile: keep dumpfile pages in a cache
In-Reply-To: <20120903124233.61eafa52ffaed6a38a23710d@mxc.nes.nec.co.jp>
References: <201208281949.50286.ptesarik@suse.cz>
 <20120903124233.61eafa52ffaed6a38a23710d@mxc.nes.nec.co.jp>
Message-ID: <201209030904.03661.ptesarik@suse.cz>

Dne Po 3. z??? 2012 05:42:33 Atsushi Kumagai napsal(a):
> Hello Petr,
> 
> On Tue, 28 Aug 2012 19:49:49 +0200
> 
> Petr Tesarik <ptesarik at suse.cz> wrote:
> > Add a simple cache for pages read from the dumpfile.
> > 
> > This is a big win if we read consecutive data from one page, e.g.
> > page descriptors, or even page table entries.
> > 
> > Note that makedumpfile now always reads a complete page. This was already
> > the case with kdump-compressed and sadump formats, but makedumpfile was
> > throwing most of the data away. For the kdump-compressed case, we may
> > actually save a lot of decompression, too.
> > 
> > I tried to keep the cache small to minimize memory footprint, but it
> > should be big enough to hold all pages to do 4-level paging plus some
> > data. This is needed e.g. for vmalloc areas or Xen page frame table
> > data, which are not contiguous in physical memory.
> > 
> > Signed-off-by: Petr Tesarik <ptesarik at suse.cz>
> 
> It's interesting to me. I want to know how performance will be improved
> with this patch, so do you have speed measurements ?

Not really. I only measured the hit/miss ratio, and with filtering Xen domU 
and dump level 0, I got the following on a small system (2G RAM):

cache hit: 1818880  cache miss: 1873

The improvement isn't much for non-Xen case, because the hits are mostly due 
to virtual-to-physical translations, and most of Linux data is stored at 
virtual addresses that can be resolved by adding/subtracting a fixed offset.

Of course, you will also win only the syscall overhead, because Linux keeps 
the data in the kernel pagecache anyway. I'll measure the times for you on a 
reasonably large system (~256G) and send the results here.

Regards,
Petr Tesarik
SUSE Linux


From kumagai-atsushi at mxc.nes.nec.co.jp  Mon Sep  3 03:37:38 2012
From: kumagai-atsushi at mxc.nes.nec.co.jp (Atsushi Kumagai)
Date: Mon, 3 Sep 2012 16:37:38 +0900
Subject: [PATCH 03/16] [PATCH v3 3/12] Change the function related to
 excluding unnecessary pages.
In-Reply-To: <20120903.111335.108627870.d.hatayama@jp.fujitsu.com>
References: <20120830164422.8d05cbcdd650398d5d5cbad9@mxc.nes.nec.co.jp>
 <20120830164701.b64acec40a0bc1bac9b3457e@mxc.nes.nec.co.jp>
 <20120903.111335.108627870.d.hatayama@jp.fujitsu.com>
Message-ID: <20120903163738.729e012c56a4e23063214b47@mxc.nes.nec.co.jp>

Hello HATAYAMA-san,

On Mon, 03 Sep 2012 11:13:35 +0900 (JST)
HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com> wrote:

> From: Atsushi Kumagai <kumagai-atsushi at mxc.nes.nec.co.jp>
> Subject: [PATCH 03/16] [PATCH v3 3/12] Change the function related to excluding unnecessary pages.
> Date: Thu, 30 Aug 2012 16:47:01 +0900
> 
> > From: Atsushi Kumagai <kumagai-atsushi at mxc.nes.nec.co.jp>
> > Date: Thu, 23 Aug 2012 17:49:16 +0900
> > Subject: [PATCH 03/16] [PATCH v3 3/12] Change the function related to excluding unnecessary pages.
> <cut>
> > +int
> > +exclude_unnecessary_pages_cyclic(void)
> > +{
> > +	unsigned int mm;
> > +	struct mem_map_data *mmd;
> > +
> > +	/*
> > +	 * Copy 1st-bitmap to 2nd-bitmap.
> > +	 */
> > +	copy_bitmap_cyclic();
> > +
> > +	if (info->dump_level & DL_EXCLUDE_FREE)
> > +		if (!exclude_free_page())
> > +			return FALSE;
> > +
> > +	/*
> > +	 * Exclude cache pages, cache private pages, user data pages, and free pages.
> > +	 */
> > +	if (info->dump_level & DL_EXCLUDE_CACHE ||
> > +	    info->dump_level & DL_EXCLUDE_CACHE_PRI ||
> > +	    info->dump_level & DL_EXCLUDE_USER_DATA) {
> > +		for (mm = 0; mm < info->num_mem_map; mm++) {
> > +
> > +			mmd = &info->mem_map_data[mm];
> > +
> > +			if (mmd->mem_map == NOT_MEMMAP_ADDR)
> > +				continue;
> > +
> > +			if (mmd->pfn_end >= info->cyclic_start_pfn || mmd->pfn_start <= info->cyclic_end_pfn) {
> > +				if (!__exclude_unnecessary_pages(mmd->mem_map,
> > +								 mmd->pfn_start, mmd->pfn_end))
> > +					return FALSE;
> > +			}
> > +		}
> > +	}
> 
> This patch misses reporting the time consumed for excluding necessary
> pages. I noticed this during benchmarking. Here is the patch I used at
> the time, but I wrote this version over your patch set.
 
Thank you for pointing out my mistake.
I'll merge the fix below into [PATCH 03/16].


Thanks
Atsushi Kumagai

>     Report the time consumed for excluding unnecessary pages in cyclic mode
> 
>     Here is the example:
> 
>     [Before]
>     STEP [Excluding free pages       ] : 0.500269 seconds
>     STEP [Excluding free pages       ] : 0.002081 seconds
>     STEP [Copying data               ] : 2.115097 seconds
> 
>     [After]
> 
>     STEP [Excluding free pages       ] : 0.002148 seconds
>     STEP [Excluding unnecessary pages] : 0.015641 seconds
>     STEP [Excluding free pages       ] : 0.002130 seconds
>     STEP [Excluding unnecessary pages] : 0.024436 seconds
>     STEP [Copying data               ] : 0.211287 seconds
> 
> diff --git a/makedumpfile.c b/makedumpfile.c
> index 0a43181..caac37b 100644
> --- a/makedumpfile.c
> +++ b/makedumpfile.c
> @@ -3882,6 +3882,7 @@ exclude_unnecessary_pages_cyclic(void)
>  {
>         unsigned int mm;
>         struct mem_map_data *mmd;
> +       struct timeval tv_start;
> 
>         /*
>          * Copy 1st-bitmap to 2nd-bitmap.
> @@ -3898,8 +3899,13 @@ exclude_unnecessary_pages_cyclic(void)
>         if (info->dump_level & DL_EXCLUDE_CACHE ||
>             info->dump_level & DL_EXCLUDE_CACHE_PRI ||
>             info->dump_level & DL_EXCLUDE_USER_DATA) {
> +
> +               gettimeofday(&tv_start, NULL);
> +
>                 for (mm = 0; mm < info->num_mem_map; mm++) {
> 
> +                       print_progress(PROGRESS_UNN_PAGES, mm, info->num_mem_map);
> +
>                         mmd = &info->mem_map_data[mm];
> 
>                         if (mmd->mem_map == NOT_MEMMAP_ADDR)
> @@ -3911,6 +3917,12 @@ exclude_unnecessary_pages_cyclic(void)
>                                         return FALSE;
>                         }
>                 }
> +
> +               /*
> +                * print [100 %]
> +                */
> +               print_progress(PROGRESS_UNN_PAGES, info->num_mem_map, info->num_mem_map);
> +               print_execution_time(PROGRESS_UNN_PAGES, &tv_start);
>         }
> 
>         return TRUE;
> 
> Thanks.
> HATAYAMA, Daisuke


From kumagai-atsushi at mxc.nes.nec.co.jp  Mon Sep  3 22:45:23 2012
From: kumagai-atsushi at mxc.nes.nec.co.jp (Atsushi Kumagai)
Date: Tue, 4 Sep 2012 11:45:23 +0900
Subject: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep
 memory usage constant.
In-Reply-To: <20120903.121637.204037088.d.hatayama@jp.fujitsu.com>
References: <20120830164422.8d05cbcdd650398d5d5cbad9@mxc.nes.nec.co.jp>
 <20120830164521.0b07c16fe2993dd8afafc79b@mxc.nes.nec.co.jp>
 <20120903.115057.275187572.d.hatayama@jp.fujitsu.com>
 <20120903.121637.204037088.d.hatayama@jp.fujitsu.com>
Message-ID: <20120904114523.e4adee9dddf970aa9a81ac00@mxc.nes.nec.co.jp>

Hello HATAYAMA-san,

On Mon, 03 Sep 2012 12:16:37 +0900 (JST)
HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com> wrote:

> From: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>
> Subject: Re: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep memory usage constant.
> Date: Mon, 3 Sep 2012 11:50:57 +0900
> 
> > From: Atsushi Kumagai <kumagai-atsushi at mxc.nes.nec.co.jp>
> > Subject: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep memory usage constant.
> > Date: Thu, 30 Aug 2012 16:45:21 +0900
> > 
> > <cut>
> > 
> >> diff --git a/makedumpfile.c b/makedumpfile.c
> >> index d024e95..21bb55a 100644
> >> --- a/makedumpfile.c
> >> +++ b/makedumpfile.c
> >> @@ -2553,6 +2553,8 @@ initial(void)
> >>  							info->name_memory);
> >>  			return FALSE;
> >>  		}
> >> +		info->flag_cyclic = FALSE;
> >> +
> > 
> > Please disable cyclic mode on sadump dumpfiles, too.

I will take care of sadump (and Xen) in the same way as for refiltering.

> Also, there's no information to users about disabling cyclic mode.
> Now switching from cyclic to normal mode is implicitly done. This is
> confusing. I think some message indicating that, is necessary.

As you said, it is unkind that no message is displayed.
I will show message as below when running mode is switched.

  MSG("Switched running mode from cyclic to non-cyclic,\n");
  MSG("because cyclic mode doesn't support sadump format.\n");


BTW, cyclic mode doesn't support the three below now.

 - Xen
 - refiltering
 - sadump

I will support Xen after Xen4 patch-set is merged.

On the other hand, I think the bottom two will be used in the 1st kernel
and makedumpfile can allocate enough memory, so cyclic mode isn't necessary
for them.
Therefore, I won't support them now. What do you think ?


Thanks
Atsushi Kumagai


From d.hatayama at jp.fujitsu.com  Mon Sep  3 23:21:11 2012
From: d.hatayama at jp.fujitsu.com (HATAYAMA Daisuke)
Date: Tue, 04 Sep 2012 12:21:11 +0900 (JST)
Subject: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep
 memory usage constant.
In-Reply-To: <20120904114523.e4adee9dddf970aa9a81ac00@mxc.nes.nec.co.jp>
References: <20120903.115057.275187572.d.hatayama@jp.fujitsu.com>
 <20120903.121637.204037088.d.hatayama@jp.fujitsu.com>
 <20120904114523.e4adee9dddf970aa9a81ac00@mxc.nes.nec.co.jp>
Message-ID: <20120904.122111.407226681.d.hatayama@jp.fujitsu.com>

From: Atsushi Kumagai <kumagai-atsushi at mxc.nes.nec.co.jp>
Subject: Re: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep memory usage constant.
Date: Tue, 4 Sep 2012 11:45:23 +0900

> Hello HATAYAMA-san,
> 
> On Mon, 03 Sep 2012 12:16:37 +0900 (JST)
> HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com> wrote:
> 
>> From: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>
>> Subject: Re: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep memory usage constant.
>> Date: Mon, 3 Sep 2012 11:50:57 +0900
>> 
>> > From: Atsushi Kumagai <kumagai-atsushi at mxc.nes.nec.co.jp>
>> > Subject: [PATCH 01/16] [PATCH v3 1/12] Introduce cyclic mode to keep memory usage constant.
>> > Date: Thu, 30 Aug 2012 16:45:21 +0900
>> > 
>> > <cut>
>> > 
>> >> diff --git a/makedumpfile.c b/makedumpfile.c
>> >> index d024e95..21bb55a 100644
>> >> --- a/makedumpfile.c
>> >> +++ b/makedumpfile.c
>> >> @@ -2553,6 +2553,8 @@ initial(void)
>> >>  							info->name_memory);
>> >>  			return FALSE;
>> >>  		}
>> >> +		info->flag_cyclic = FALSE;
>> >> +
>> > 
>> > Please disable cyclic mode on sadump dumpfiles, too.
> 
> I will take care of sadump (and Xen) in the same way as for refiltering.
> 

Thanks.

>> Also, there's no information to users about disabling cyclic mode.
>> Now switching from cyclic to normal mode is implicitly done. This is
>> confusing. I think some message indicating that, is necessary.
> 
> As you said, it is unkind that no message is displayed.
> I will show message as below when running mode is switched.
> 
>   MSG("Switched running mode from cyclic to non-cyclic,\n");
>   MSG("because cyclic mode doesn't support sadump format.\n");
> 

For refiltering case, too, just in case.

> 
> BTW, cyclic mode doesn't support the three below now.
> 
>  - Xen
>  - refiltering
>  - sadump
> 
> I will support Xen after Xen4 patch-set is merged.
> 
> On the other hand, I think the bottom two will be used in the 1st kernel
> and makedumpfile can allocate enough memory, so cyclic mode isn't necessary
> for them.
> Therefore, I won't support them now. What do you think ?
> 

Yes, I think so, too.

Thanks.
HATAYAMA, Daisuke



From dyoung at redhat.com  Wed Sep  5 01:44:45 2012
From: dyoung at redhat.com (Dave Young)
Date: Wed, 5 Sep 2012 13:44:45 +0800
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
Message-ID: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>


In case efi booting, kdump need kernel parameter noefi and acpi_rsdp=
to disable efi reinit and retrieve the acpi root table physical address.

Add a function cmdline_add_efi to get the address from /sys/firmware/efi/systab
If there's no such file or read fail the function will just do nothing.

Tested efi boot Fedora 17 on thinkpad T420.

Signed-off-by: Dave Young <dyoung at redhat.com>
---
 kexec/arch/i386/crashdump-x86.c |   47 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

--- kexec-tools.orig/kexec/arch/i386/crashdump-x86.c
+++ kexec-tools/kexec/arch/i386/crashdump-x86.c
@@ -27,6 +27,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <fcntl.h>
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 #include "../../kexec-syscall.h"
@@ -658,6 +659,51 @@ static int cmdline_add_memmap_acpi(char 
 	return 0;
 }
 
+/* Appends 'noefi acpi_rsdp=' commandline for efi boot crash dump */
+static void cmdline_add_efi(char *cmdline)
+{
+	int cmdlen, len, fd, ret, i = 0;
+	char str_efi[64], str_tmp[32];
+
+	memset(str_efi, 0x0, sizeof(str_efi));
+	memset(str_tmp, 0x0, sizeof(str_tmp));
+	snprintf(str_efi, 18, "%s", " noefi acpi_rsdp=");
+
+	fd = open("/sys/firmware/efi/systab", O_RDONLY);
+	if (fd < 0)
+		return;
+
+	while(1) {
+		ret = read(fd, &str_tmp[i], 1);
+		if (ret <= 0)
+			goto out_close;
+		if (str_tmp[i] == '\n') {
+			str_tmp[i] = '\0';
+			break;
+		}
+		i++;
+	}
+
+	if (!(strncmp(str_tmp, "ACPI20=", 7)))
+		strcat(str_efi, &str_tmp[7]);
+	else if (!(strncmp(str_tmp, "ACPI=", 5)))
+		strcat(str_efi, &str_tmp[5]);
+	else
+		goto out_close;
+
+	len = strlen(str_efi);
+	cmdlen = strlen(cmdline) + len;
+	if (cmdlen > (COMMAND_LINE_SIZE - 1))
+		die("Command line overflow\n");
+	strcat(cmdline, str_efi);
+
+	dbgprintf("Command line after adding efi\n");
+	dbgprintf("%s\n", cmdline);
+
+out_close:
+	close(fd);
+}
+
 static void get_backup_area(unsigned long *start, unsigned long *end)
 {
 	const char *iomem = proc_iomem();
@@ -830,6 +876,7 @@ int load_crashdump_segments(struct kexec
 	if (delete_memmap(memmap_p, elfcorehdr, memsz) < 0)
 		return -1;
 	cmdline_add_memmap(mod_cmdline, memmap_p);
+	cmdline_add_efi(mod_cmdline);
 	cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
 
 	/* Inform second kernel about the presence of ACPI tables. */


From horms at verge.net.au  Wed Sep  5 03:45:55 2012
From: horms at verge.net.au (Simon Horman)
Date: Wed, 5 Sep 2012 16:45:55 +0900
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
Message-ID: <20120905074550.GA11575@verge.net.au>

On Wed, Sep 05, 2012 at 01:44:45PM +0800, Dave Young wrote:
> 
> In case efi booting, kdump need kernel parameter noefi and acpi_rsdp=
> to disable efi reinit and retrieve the acpi root table physical address.
> 
> Add a function cmdline_add_efi to get the address from /sys/firmware/efi/systab
> If there's no such file or read fail the function will just do nothing.
> 
> Tested efi boot Fedora 17 on thinkpad T420.

Hi Dave,

conceptually I am fine with this patch.
However, I do have a few nits in relation to the string handling
as explained below.

> 
> Signed-off-by: Dave Young <dyoung at redhat.com>
> ---
>  kexec/arch/i386/crashdump-x86.c |   47 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 47 insertions(+)
> 
> --- kexec-tools.orig/kexec/arch/i386/crashdump-x86.c
> +++ kexec-tools/kexec/arch/i386/crashdump-x86.c
> @@ -27,6 +27,7 @@
>  #include <sys/types.h>
>  #include <sys/stat.h>
>  #include <unistd.h>
> +#include <fcntl.h>
>  #include "../../kexec.h"
>  #include "../../kexec-elf.h"
>  #include "../../kexec-syscall.h"
> @@ -658,6 +659,51 @@ static int cmdline_add_memmap_acpi(char 
>  	return 0;
>  }
>  
> +/* Appends 'noefi acpi_rsdp=' commandline for efi boot crash dump */
> +static void cmdline_add_efi(char *cmdline)
> +{
> +	int cmdlen, len, fd, ret, i = 0;
> +	char str_efi[64], str_tmp[32];
> +
> +	memset(str_efi, 0x0, sizeof(str_efi));
> +	memset(str_tmp, 0x0, sizeof(str_tmp));
> +	snprintf(str_efi, 18, "%s", " noefi acpi_rsdp=");

strncpy() might be be easier on the eyes.

> +
> +	fd = open("/sys/firmware/efi/systab", O_RDONLY);
> +	if (fd < 0)
> +		return;
> +
> +	while(1) {
> +		ret = read(fd, &str_tmp[i], 1);
> +		if (ret <= 0)
> +			goto out_close;
> +		if (str_tmp[i] == '\n') {
> +			str_tmp[i] = '\0';
> +			break;
> +		}
> +		i++;
> +	}

It seems to me that the above code may overflow str_tmp.

Also, I wonder if read(fd, str_tmp, sizeof str_tmp) might make
things a bit easier over all.

Finally, I have a personal preference for "a + i" over "&a[i]".
Though I'm not going to get excited about it.

> +
> +	if (!(strncmp(str_tmp, "ACPI20=", 7)))
> +		strcat(str_efi, &str_tmp[7]);
> +	else if (!(strncmp(str_tmp, "ACPI=", 5)))
> +		strcat(str_efi, &str_tmp[5]);
> +	else
> +		goto out_close;

I wonder if strncat() would be better above, though I don't think
an overflow can actually occur if str_tmp is null-terminated.

> +
> +	len = strlen(str_efi);
> +	cmdlen = strlen(cmdline) + len;
> +	if (cmdlen > (COMMAND_LINE_SIZE - 1))
> +		die("Command line overflow\n");
> +	strcat(cmdline, str_efi);
> +
> +	dbgprintf("Command line after adding efi\n");
> +	dbgprintf("%s\n", cmdline);
> +
> +out_close:
> +	close(fd);
> +}
> +
>  static void get_backup_area(unsigned long *start, unsigned long *end)
>  {
>  	const char *iomem = proc_iomem();
> @@ -830,6 +876,7 @@ int load_crashdump_segments(struct kexec
>  	if (delete_memmap(memmap_p, elfcorehdr, memsz) < 0)
>  		return -1;
>  	cmdline_add_memmap(mod_cmdline, memmap_p);
> +	cmdline_add_efi(mod_cmdline);
>  	cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
>  
>  	/* Inform second kernel about the presence of ACPI tables. */
> 


From indou.takao at jp.fujitsu.com  Wed Sep  5 07:09:58 2012
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Wed, 05 Sep 2012 20:09:58 +0900
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <20120806203902.GH25559@redhat.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com> <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com>
Message-ID: <50473306.1070803@jp.fujitsu.com>

(2012/08/07 5:39), Vivek Goyal wrote:
> On Mon, Aug 06, 2012 at 01:30:47PM +0900, Takao Indoh wrote:
>> Hi Vivek,
>>
>> (2012/08/03 20:46), Vivek Goyal wrote:
>>> On Fri, Aug 03, 2012 at 08:24:31PM +0900, Takao Indoh wrote:
>>>> Hi all,
>>>>
>>>> This patch adds kernel parameter "reset_pcie_devices" which resets PCIe
>>>> devices at boot time to address DMA problem on kdump with iommu. When
>>>> this parameter is specified, a hot reset is triggered on each PCIe root
>>>> port and downstream port to reset its downstream endpoint.
>>>
>>> Hi Takao,
>>>
>>> Why not use existing "reset_devices" parameter instead of introducing
>>> a new one?
>>
>> "reset_devices" is used for each driver to reset their own device, and
>> this patch resets all devices forcibly, so I thought they were different
>> things.
>
> Yes reset_devices currently is used for driver to reset its device. I
> thought one could very well extend its reach to reset pci express devices
> at bus level.
>
> Having them separate is not going to be much useful from kdump
> perspective. We will end up passing both reset_devices and
> reset_pcie_devices to second kernel whill lead to bus level reset as well
> as device level reset.
>
> Ideal situation would be that somehow detect that bus level reset has been
> done and skip device level reset (assuming bus level reset obviates the
> need of device level reset, please correct me if that's not the case).
>
> After pcie reset, can we store the state in a variable and drivers can
> use that variable to check if PCIe level reset was done or not. If yes,
> skip device level reset (Assuming driver knows that device is on a
> PCIe slot).
>
> In that case we will not have to introduce new kernel command line, and
> also avoid double reset?
  
I found a problem when testing my patch on some machines.

Originally there are two problems in kdump kernel when iommu is enabled;
DMAR error and PCI SERR. I thought they are fixed by my patch, but I
noticed that PCI SERR is still detected after applying the patch. It
seems that something happens when Interrupt Remapping is initialized in
kdump kernel.

Therefore resetting devices has to be done before enable_IR() is
called. I have three ideas for it.

  (i) Resetting devices in 1st kernel(panic kernel)
  We can reset devices before jumping into 2nd kernel. Of course it may
  be dangerous to scan pci device tree and call PCI functions in panic'd
  kernel. Beforehand we need to collect device information so that only
  minimal code could run on panic.

  (ii) Resetting devices in purgatory
  It seems to be be appropriate place to do this, but I'm not sure
  where I can save/restore PCI config when resetting devices in
  purgatory.

  (iii) Resetting devices in 2nd kernel(kdump kernel)
  Important point is to do reset before enable_IR() is called as I wrote
  above. I think I should add new function to do reset into
  arch/x86/pci/early.c and call it in setup_arch like
  early_dump_pci_devices() or early_quirks().

Any comments?

Thanks,
Takao Indoh



From matthew.leach at arm.com  Wed Sep  5 07:44:00 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Wed,  5 Sep 2012 12:44:00 +0100
Subject: [RFC PATCH 1/4] Fix an overflow bug with address comparison
In-Reply-To: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
Message-ID: <1346845443-32242-2-git-send-email-matthew.leach@arm.com>

The variables mstart and mend are assigned the values of
mem_region[i].start and mem_region[i].end which are of the type
unsigned long long. Ensure that mstart and mend are of the same data
type to prevent address overflow.

Signed-off-by: Matthew Leach <matthew.leach at arm.com>
---
 kexec/kexec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kexec/kexec.c b/kexec/kexec.c
index 8928be0..c7b38e3 100644
--- a/kexec/kexec.c
+++ b/kexec/kexec.c
@@ -108,7 +108,7 @@ int valid_memory_range(struct kexec_info *info,
 		return 0;
 	}
 	for (i = 0; i < info->memory_ranges; i++) {
-		unsigned long mstart, mend;
+		unsigned long long mstart, mend;
 		/* Only consider memory ranges */
 		if (info->memory_range[i].type != RANGE_RAM)
 			continue;
-- 
1.7.12



From matthew.leach at arm.com  Wed Sep  5 07:43:59 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Wed,  5 Sep 2012 12:43:59 +0100
Subject: [RFC PATCH 0/4]  Add device-tree support to kexec-tools for ARM
Message-ID: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>

Hi all,

Running a kexec() on newer ARM platforms has become an issue as
information about the platform that is presented via device-tree is
required to boot a new kernel.

The ATAGs kernel code is re-used, replacing the ATAGs with a
device-tree blob so that only kexec-tools needs to be changed. There
are two options for generating a dtb to be passed to the kernel from
kexec-tools: 1) Read in the device-tree that is exposed in
/proc/device-tree and flatten this out into a dtb.  2) Allow the user
to specify a dtb file on the command line.  These blobs are then
loaded into memory before the kernel image and the address passed
through to r2, as stated in the ARM booting documentation.

All comments welcome,
Matt

Matthew Leach (4):
  Fix an overflow bug with address comparison
  Move libfdt to a generic location
  Add the dtc for device-tree manipulation
  Add device tree support to the ARM platform

 kexec/arch/arm/Makefile                            |  10 +
 kexec/arch/arm/include/arch/options.h              |   6 +-
 kexec/arch/arm/kexec-zImage-arm.c                  | 140 ++++-
 kexec/arch/ppc/Makefile                            |   8 +-
 kexec/kexec.c                                      |   2 +-
 util_lib/Makefile                                  |   2 +
 util_lib/dtc/Makefile.dtc                          |   9 +
 util_lib/dtc/data.c                                | 321 ++++++++++
 util_lib/dtc/dtc.c                                 |  44 ++
 util_lib/dtc/dtc.h                                 | 244 ++++++++
 util_lib/dtc/flattree.c                            | 649 +++++++++++++++++++++
 util_lib/dtc/fstree.c                              |  91 +++
 util_lib/dtc/livetree.c                            | 579 ++++++++++++++++++
 util_lib/dtc/srcpos.c                              | 252 ++++++++
 util_lib/dtc/srcpos.h                              |  87 +++
 util_lib/dtc/util.c                                |  59 ++
 util_lib/dtc/util.h                                |  56 ++
 util_lib/dtc/version_gen.h                         |   1 +
 .../arch/ppc => util_lib}/libfdt/Makefile.libfdt   |   8 +-
 {kexec/arch/ppc => util_lib}/libfdt/TODO           |   0
 {kexec/arch/ppc => util_lib}/libfdt/fdt.c          |   0
 {kexec/arch/ppc => util_lib}/libfdt/fdt.h          |   0
 {kexec/arch/ppc => util_lib}/libfdt/fdt_ro.c       |   0
 {kexec/arch/ppc => util_lib}/libfdt/fdt_rw.c       |   0
 {kexec/arch/ppc => util_lib}/libfdt/fdt_strerror.c |   0
 {kexec/arch/ppc => util_lib}/libfdt/fdt_sw.c       |   0
 {kexec/arch/ppc => util_lib}/libfdt/fdt_wip.c      |   0
 {kexec/arch/ppc => util_lib}/libfdt/libfdt.h       |   0
 {kexec/arch/ppc => util_lib}/libfdt/libfdt_env.h   |   0
 .../arch/ppc => util_lib}/libfdt/libfdt_internal.h |   0
 30 files changed, 2553 insertions(+), 15 deletions(-)
 create mode 100644 util_lib/dtc/Makefile.dtc
 create mode 100644 util_lib/dtc/data.c
 create mode 100644 util_lib/dtc/dtc.c
 create mode 100644 util_lib/dtc/dtc.h
 create mode 100644 util_lib/dtc/flattree.c
 create mode 100644 util_lib/dtc/fstree.c
 create mode 100644 util_lib/dtc/livetree.c
 create mode 100644 util_lib/dtc/srcpos.c
 create mode 100644 util_lib/dtc/srcpos.h
 create mode 100644 util_lib/dtc/util.c
 create mode 100644 util_lib/dtc/util.h
 create mode 100644 util_lib/dtc/version_gen.h
 rename {kexec/arch/ppc => util_lib}/libfdt/Makefile.libfdt (60%)
 rename {kexec/arch/ppc => util_lib}/libfdt/TODO (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt.h (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt_ro.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt_rw.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt_strerror.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt_sw.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt_wip.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/libfdt.h (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/libfdt_env.h (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/libfdt_internal.h (100%)

-- 
1.7.12



From matthew.leach at arm.com  Wed Sep  5 07:44:01 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Wed,  5 Sep 2012 12:44:01 +0100
Subject: [RFC PATCH 2/4] Move libfdt to a generic location
In-Reply-To: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
Message-ID: <1346845443-32242-3-git-send-email-matthew.leach@arm.com>

Move the libfdt library to a more accessible location for other
architectures and update the ppc makefile to reflect these changes.

Signed-off-by: Matthew Leach <matthew.leach at arm.com>
---
 kexec/arch/ppc/Makefile                               | 8 ++++----
 {kexec/arch/ppc => util_lib}/libfdt/Makefile.libfdt   | 8 ++++----
 {kexec/arch/ppc => util_lib}/libfdt/TODO              | 0
 {kexec/arch/ppc => util_lib}/libfdt/fdt.c             | 0
 {kexec/arch/ppc => util_lib}/libfdt/fdt.h             | 0
 {kexec/arch/ppc => util_lib}/libfdt/fdt_ro.c          | 0
 {kexec/arch/ppc => util_lib}/libfdt/fdt_rw.c          | 0
 {kexec/arch/ppc => util_lib}/libfdt/fdt_strerror.c    | 0
 {kexec/arch/ppc => util_lib}/libfdt/fdt_sw.c          | 0
 {kexec/arch/ppc => util_lib}/libfdt/fdt_wip.c         | 0
 {kexec/arch/ppc => util_lib}/libfdt/libfdt.h          | 0
 {kexec/arch/ppc => util_lib}/libfdt/libfdt_env.h      | 0
 {kexec/arch/ppc => util_lib}/libfdt/libfdt_internal.h | 0
 13 files changed, 8 insertions(+), 8 deletions(-)
 rename {kexec/arch/ppc => util_lib}/libfdt/Makefile.libfdt (60%)
 rename {kexec/arch/ppc => util_lib}/libfdt/TODO (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt.h (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt_ro.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt_rw.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt_strerror.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt_sw.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/fdt_wip.c (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/libfdt.h (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/libfdt_env.h (100%)
 rename {kexec/arch/ppc => util_lib}/libfdt/libfdt_internal.h (100%)

diff --git a/kexec/arch/ppc/Makefile b/kexec/arch/ppc/Makefile
index e868917..38f4257 100644
--- a/kexec/arch/ppc/Makefile
+++ b/kexec/arch/ppc/Makefile
@@ -1,7 +1,7 @@
 #
 # kexec ppc (linux booting linux)
 #
-include $(srcdir)/kexec/arch/ppc/libfdt/Makefile.libfdt
+include $(srcdir)/util_lib/libfdt/Makefile.libfdt
 
 ppc_KEXEC_SRCS =  kexec/arch/ppc/kexec-ppc.c
 ppc_KEXEC_SRCS += kexec/arch/ppc/kexec-elf-ppc.c
@@ -13,14 +13,14 @@ ppc_KEXEC_SRCS += kexec/arch/ppc/ppc-setup-dol.S
 ppc_KEXEC_SRCS += kexec/arch/ppc/fixup_dtb.c
 ppc_KEXEC_SRCS += kexec/arch/ppc/fs2dt.c
 ppc_KEXEC_SRCS += kexec/arch/ppc/crashdump-powerpc.c
+ppc_KEXEC_SRCS += kexec/arch/ppc/libfdt-wrapper.c
 
 ppc_UIMAGE = kexec/kexec-uImage.c
 
-libfdt_SRCS = kexec/arch/ppc/libfdt-wrapper.c
-libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/arch/ppc/libfdt/%)
+libfdt_SRCS += $(LIBFDT_SRCS:%=util_lib/libfdt/%)
 ppc_ARCH_REUSE_INITRD =
 
-CPPFLAGS+=-I$(srcdir)/kexec/arch/$(ARCH)/libfdt
+CPPFLAGS+=-I$(srcdir)/util_lib/libfdt
 
 ppc_KEXEC_SRCS += $(libfdt_SRCS)
 
diff --git a/kexec/arch/ppc/libfdt/Makefile.libfdt b/util_lib/libfdt/Makefile.libfdt
similarity index 60%
rename from kexec/arch/ppc/libfdt/Makefile.libfdt
rename to util_lib/libfdt/Makefile.libfdt
index 1d1b295..f34595e 100644
--- a/kexec/arch/ppc/libfdt/Makefile.libfdt
+++ b/util_lib/libfdt/Makefile.libfdt
@@ -7,7 +7,7 @@ LIBFDT_INCLUDES = fdt.h libfdt.h
 LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
 
-dist += kexec/arch/ppc/libfdt/Makefile.libfdt				\
-	kexec/arch/ppc/libfdt/fdt.h kexec/arch/ppc/libfdt/libfdt.h	\
-	kexec/arch/ppc/libfdt/libfdt_env.h				\
-	kexec/arch/ppc/libfdt/libfdt_internal.h
+dist += util_lib/libfdt/Makefile.libfdt				\
+	util_lib/libfdt/fdt.h util_lib/libfdt/libfdt.h	\
+	util_lib/libfdt/libfdt_env.h				\
+	util_lib/libfdt/libfdt_internal.h
diff --git a/kexec/arch/ppc/libfdt/TODO b/util_lib/libfdt/TODO
similarity index 100%
rename from kexec/arch/ppc/libfdt/TODO
rename to util_lib/libfdt/TODO
diff --git a/kexec/arch/ppc/libfdt/fdt.c b/util_lib/libfdt/fdt.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt.c
rename to util_lib/libfdt/fdt.c
diff --git a/kexec/arch/ppc/libfdt/fdt.h b/util_lib/libfdt/fdt.h
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt.h
rename to util_lib/libfdt/fdt.h
diff --git a/kexec/arch/ppc/libfdt/fdt_ro.c b/util_lib/libfdt/fdt_ro.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt_ro.c
rename to util_lib/libfdt/fdt_ro.c
diff --git a/kexec/arch/ppc/libfdt/fdt_rw.c b/util_lib/libfdt/fdt_rw.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt_rw.c
rename to util_lib/libfdt/fdt_rw.c
diff --git a/kexec/arch/ppc/libfdt/fdt_strerror.c b/util_lib/libfdt/fdt_strerror.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt_strerror.c
rename to util_lib/libfdt/fdt_strerror.c
diff --git a/kexec/arch/ppc/libfdt/fdt_sw.c b/util_lib/libfdt/fdt_sw.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt_sw.c
rename to util_lib/libfdt/fdt_sw.c
diff --git a/kexec/arch/ppc/libfdt/fdt_wip.c b/util_lib/libfdt/fdt_wip.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt_wip.c
rename to util_lib/libfdt/fdt_wip.c
diff --git a/kexec/arch/ppc/libfdt/libfdt.h b/util_lib/libfdt/libfdt.h
similarity index 100%
rename from kexec/arch/ppc/libfdt/libfdt.h
rename to util_lib/libfdt/libfdt.h
diff --git a/kexec/arch/ppc/libfdt/libfdt_env.h b/util_lib/libfdt/libfdt_env.h
similarity index 100%
rename from kexec/arch/ppc/libfdt/libfdt_env.h
rename to util_lib/libfdt/libfdt_env.h
diff --git a/kexec/arch/ppc/libfdt/libfdt_internal.h b/util_lib/libfdt/libfdt_internal.h
similarity index 100%
rename from kexec/arch/ppc/libfdt/libfdt_internal.h
rename to util_lib/libfdt/libfdt_internal.h
-- 
1.7.12



From matthew.leach at arm.com  Wed Sep  5 07:44:03 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Wed,  5 Sep 2012 12:44:03 +0100
Subject: [RFC PATCH 4/4] Add device tree support to the ARM platform
In-Reply-To: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
Message-ID: <1346845443-32242-5-git-send-email-matthew.leach@arm.com>

To allow newer ARM platforms to use kexec, pass device tree
information to the kernel during boot.

By default the dtb is found from /proc/device-tree. A user can specify
a dtb file or use legacy ATAGs

Signed-off-by: Matthew Leach <matthew.leach at arm.com>
---
 kexec/arch/arm/Makefile               |  10 +++
 kexec/arch/arm/include/arch/options.h |   6 +-
 kexec/arch/arm/kexec-zImage-arm.c     | 140 ++++++++++++++++++++++++++++++++--
 3 files changed, 150 insertions(+), 6 deletions(-)

diff --git a/kexec/arch/arm/Makefile b/kexec/arch/arm/Makefile
index 288ec33..f25ce15 100644
--- a/kexec/arch/arm/Makefile
+++ b/kexec/arch/arm/Makefile
@@ -1,12 +1,22 @@
 #
 # kexec arm (linux booting linux)
 #
+include $(srcdir)/util_lib/dtc/Makefile.dtc
+
 arm_KEXEC_SRCS=  kexec/arch/arm/kexec-elf-rel-arm.c
 arm_KEXEC_SRCS+= kexec/arch/arm/kexec-zImage-arm.c
 arm_KEXEC_SRCS+= kexec/arch/arm/kexec-uImage-arm.c
 arm_KEXEC_SRCS+= kexec/arch/arm/kexec-arm.c
 arm_KEXEC_SRCS+= kexec/arch/arm/crashdump-arm.c
 
+libfdt_SRCS += $(LIBFDT_SRCS:%=util_lib/libfdt/%)
+dtc_SRCS += $(DTC_SRCS:%=util_lib/dtc/%)
+
+arm_KEXEC_SRCS+= $(libfdt_SRCS)
+arm_KEXEC_SRCS+= $(dtc_SRCS)
+
+CPPFLAGS+=-I$(srcdir)/util_lib/libfdt
+
 arm_UIMAGE = kexec/kexec-uImage.c
 arm_PHYS_TO_VIRT = kexec/arch/arm/phys_to_virt.c
 
diff --git a/kexec/arch/arm/include/arch/options.h b/kexec/arch/arm/include/arch/options.h
index d89c91f..b355c26 100644
--- a/kexec/arch/arm/include/arch/options.h
+++ b/kexec/arch/arm/include/arch/options.h
@@ -5,6 +5,8 @@
 
 #define OPT_APPEND	'a'
 #define OPT_RAMDISK	'r'
+#define OPT_DTB     (OPT_ARCH_MAX+0)
+#define OPT_ATAGS   (OPT_ARCH_MAX+1)
 
 /* Options relevant to the architecture (excluding loader-specific ones),
  * in this case none:
@@ -33,7 +35,9 @@
 	{ "command-line",	1, 0, OPT_APPEND },	\
 	{ "append",		1, 0, OPT_APPEND },	\
 	{ "initrd",		1, 0, OPT_RAMDISK },	\
-	{ "ramdisk",		1, 0, OPT_RAMDISK },
+	{ "ramdisk",		1, 0, OPT_RAMDISK },	\
+	{ "dtb",		1, 0, OPT_DTB }, 	\
+	{ "atags",		0, 0, OPT_ATAGS },
 
 #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR "a:r:"
 
diff --git a/kexec/arch/arm/kexec-zImage-arm.c b/kexec/arch/arm/kexec-zImage-arm.c
index 88a6c29..74028b8 100644
--- a/kexec/arch/arm/kexec-zImage-arm.c
+++ b/kexec/arch/arm/kexec-zImage-arm.c
@@ -13,6 +13,8 @@
 #include <unistd.h>
 #include <getopt.h>
 #include <unistd.h>
+#include <dtc.h>
+#include <libfdt.h>
 #include <arch/options.h>
 #include "../../kexec.h"
 #include "../../kexec-syscall.h"
@@ -96,6 +98,8 @@ void zImage_arm_usage(void)
 		"     --append=STRING       Set the kernel command line to STRING.\n"
 		"     --initrd=FILE         Use FILE as the kernel's initial ramdisk.\n"
 		"     --ramdisk=FILE        Use FILE as the kernel's initial ramdisk.\n"
+		"     --dtb=FILE            Use FILE as the fdt blob.\n"
+		"     --atags               Use ATAGs instead of device-tree.\n"
 		);
 }
 
@@ -208,6 +212,63 @@ int atag_arm_load(struct kexec_info *info, unsigned long base,
 	return 0;
 }
 
+void dtb_fixup_chosen_node(char **dtb_buf, off_t *buf_sz, const char *command_line,
+                           unsigned long initrd_start, unsigned long initrd_end)
+{
+	if (command_line || initrd_start != initrd_end) {
+		int chosen_offset;
+		int root_offset;
+		int command_line_len = strlen(command_line);
+		off_t new_buf_sz = *buf_sz + command_line_len + 0x50; /* extra space for new node */
+		void *new_buf = malloc(new_buf_sz);
+
+		fdt_open_into(*dtb_buf, new_buf, new_buf_sz);
+
+		root_offset = fdt_path_offset(new_buf, "/");
+		chosen_offset = fdt_path_offset(new_buf, "/chosen");
+		if (chosen_offset == -FDT_ERR_NOTFOUND) {
+			chosen_offset = fdt_add_subnode(new_buf, root_offset, "chosen");
+		}
+		if (chosen_offset < 0) {
+			fprintf(stderr, "Warning: failed to find the chosen node, a specified command line and"
+			        " initrd will not be set.\n");
+			free(new_buf);
+			return;
+		}
+
+		/*
+		 * Add the 'bootargs' proerpty to the chosen node if the command
+		 * line is specified.
+		 */
+		if (command_line) {
+			if (fdt_setprop_string(new_buf, chosen_offset,
+			                       "bootargs", command_line) < 0) {
+				fprintf(stderr, "Warning: failed to set the command line.\n");
+				free(new_buf);
+				return;
+			}
+		}
+
+		/*
+		 * Add the 'initrd-start' and 'initrd-end' properties to the
+		 * chosen node if an initrd is specified.
+		 */
+		if (initrd_start != initrd_end) {
+			if ((fdt_setprop_cell(new_buf, chosen_offset,
+			                      "initrd-start", initrd_start) < 0) ||
+			    (fdt_setprop_cell(new_buf, chosen_offset,
+			                      "initrd-end", initrd_end) < 0)) {
+				fprintf(stderr, "Warning: failed to set the initrd addresses.\n");
+				return;
+			}	
+		}
+
+		free(*dtb_buf);
+		*dtb_buf = new_buf;
+		*buf_sz = new_buf_sz;
+	}
+}
+
 int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info)
 {
@@ -222,6 +283,12 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 	off_t ramdisk_length;
 	off_t ramdisk_offset;
 	int opt;
+	int use_atags;
+	char *dtb_buf;
+	off_t dtb_length;
+	char *dtb_file;
+	off_t dtb_offset;
+
 	/* See options.h -- add any more there, too. */
 	static const struct option options[] = {
 		KEXEC_ARCH_OPTIONS
@@ -229,6 +296,8 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 		{ "append",		1, 0, OPT_APPEND },
 		{ "initrd",		1, 0, OPT_RAMDISK },
 		{ "ramdisk",		1, 0, OPT_RAMDISK },
+		{ "dtb",		1, 0, OPT_DTB },
+		{ "atags",		0, 0, OPT_ATAGS },
 		{ 0, 			0, 0, 0 },
 	};
 	static const char short_options[] = KEXEC_ARCH_OPT_STR "a:r:";
@@ -241,6 +310,8 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 	ramdisk = 0;
 	ramdisk_buf = 0;
 	ramdisk_length = 0;
+	use_atags = 0;
+	dtb_file = NULL;
 	while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
 		switch(opt) {
 		default:
@@ -257,8 +328,21 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 		case OPT_RAMDISK:
 			ramdisk = optarg;
 			break;
+		case OPT_DTB:
+			dtb_file = optarg;
+			break;
+		case OPT_ATAGS:
+			use_atags = 1;
+			break;
 		}
 	}
+
+	if (use_atags && dtb_file) {
+		fprintf(stderr, "You can only use ATAGs if you don't specify a "
+		        "dtb file.\n");
+		return -1;
+	}
+
 	if (command_line) {
 		command_line_len = strlen(command_line) + 1;
 		if (command_line_len > COMMAND_LINE_SIZE)
@@ -315,12 +399,58 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 	/* assume the maximum kernel compression ratio is 4,
 	 * and just to be safe, place ramdisk after that
 	 */
-	ramdisk_offset = base + len * 4;
+		ramdisk_offset = base + len * 4;
 
-	if (atag_arm_load(info, base + atag_offset,
-			 command_line, command_line_len,
-			 ramdisk_buf, ramdisk_length, ramdisk_offset) == -1)
-		return -1;
+	if (use_atags) {
+		/*
+		 * use ATAGs from /proc/atags
+		 */
+		if (atag_arm_load(info, base + atag_offset,
+		                  command_line, command_line_len,
+		                  ramdisk_buf, ramdisk_length, ramdisk_offset) == -1)
+			return -1;
+	} else {
+		/*
+		 * Read a user-specified DTB file.
+		 */
+		if (dtb_file) {
+			dtb_buf = slurp_file(dtb_file, &dtb_length);
+		} else {
+			/*
+			 * Extract the DTB from /proc/device-tree.
+			 */
+			struct boot_info *bi;
+			bi = dt_from_fs("/proc/device-tree");
+			dtb_buf = dt_to_blob_buf(&dtb_length, bi, DEFAULT_FDT_VERSION);
+		}
+
+		dtb_fixup_chosen_node(&dtb_buf, &dtb_length, command_line,
+		                      ramdisk_offset, ramdisk_offset + ramdisk_length);
+
+		if (fdt_check_header(dtb_buf) != 0) {
+			fprintf(stderr, "Invalid FDT buffer.\n");
+			return -1;
+		}
+
+		if (base + atag_offset + dtb_length > base + offset) {
+			fprintf(stderr, "DTB too large!\n");
+			return -1;
+		}
+
+		if (ramdisk) {
+			add_segment(info, ramdisk_buf, ramdisk_length,
+			            ramdisk_offset, ramdisk_length);
+		}
+
+		/* Stick the dtb at the end of the initrd and page
+		 * align it.
+		 */
+		dtb_offset = ramdisk_offset + ramdisk_length + getpagesize();
+		dtb_offset &= ~(getpagesize() - 1);
+
+		add_segment(info, dtb_buf, dtb_length,
+		            dtb_offset, dtb_length);
+	}
 
 	add_segment(info, buf, len, base + offset, len);
 
-- 
1.7.12



From horms at verge.net.au  Wed Sep  5 08:38:50 2012
From: horms at verge.net.au (Simon Horman)
Date: Wed, 5 Sep 2012 21:38:50 +0900
Subject: [RFC PATCH 0/4]  Add device-tree support to kexec-tools for ARM
In-Reply-To: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
Message-ID: <20120905123850.GA11453@verge.net.au>

On Wed, Sep 05, 2012 at 12:43:59PM +0100, Matthew Leach wrote:
> Hi all,
> 
> Running a kexec() on newer ARM platforms has become an issue as
> information about the platform that is presented via device-tree is
> required to boot a new kernel.
> 
> The ATAGs kernel code is re-used, replacing the ATAGs with a
> device-tree blob so that only kexec-tools needs to be changed. There
> are two options for generating a dtb to be passed to the kernel from
> kexec-tools: 1) Read in the device-tree that is exposed in
> /proc/device-tree and flatten this out into a dtb.  2) Allow the user
> to specify a dtb file on the command line.  These blobs are then
> loaded into memory before the kernel image and the address passed
> through to r2, as stated in the ARM booting documentation.

Hi Matt,

are you aware that I posted patches to add ARM DT support
to kexec-tools a few weeks ago?

I'm not particularly concerned which version goes in,
but perhaps we can learn from each others efforts.


From matthew.leach at arm.com  Wed Sep  5 07:44:02 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Wed,  5 Sep 2012 12:44:02 +0100
Subject: [RFC PATCH 3/4] Add the dtc for device-tree manipulation
In-Reply-To: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
Message-ID: <1346845443-32242-4-git-send-email-matthew.leach@arm.com>

The dtc includes functions for generating a dtb for the currently
running kernel that is exposed in /proc/device-tree. Include the dtc
so a dtb can be generated for a new kernel without the user having to
obtain a dtb file.

Signed-off-by: Matthew Leach <matthew.leach at arm.com>
---
 util_lib/Makefile          |   2 +
 util_lib/dtc/Makefile.dtc  |   9 +
 util_lib/dtc/data.c        | 321 ++++++++++++++++++++++
 util_lib/dtc/dtc.c         |  44 +++
 util_lib/dtc/dtc.h         | 244 +++++++++++++++++
 util_lib/dtc/flattree.c    | 649 +++++++++++++++++++++++++++++++++++++++++++++
 util_lib/dtc/fstree.c      |  91 +++++++
 util_lib/dtc/livetree.c    | 579 ++++++++++++++++++++++++++++++++++++++++
 util_lib/dtc/srcpos.c      | 252 ++++++++++++++++++
 util_lib/dtc/srcpos.h      |  87 ++++++
 util_lib/dtc/util.c        |  59 +++++
 util_lib/dtc/util.h        |  56 ++++
 util_lib/dtc/version_gen.h |   1 +
 13 files changed, 2394 insertions(+)
 create mode 100644 util_lib/dtc/Makefile.dtc
 create mode 100644 util_lib/dtc/data.c
 create mode 100644 util_lib/dtc/dtc.c
 create mode 100644 util_lib/dtc/dtc.h
 create mode 100644 util_lib/dtc/flattree.c
 create mode 100644 util_lib/dtc/fstree.c
 create mode 100644 util_lib/dtc/livetree.c
 create mode 100644 util_lib/dtc/srcpos.c
 create mode 100644 util_lib/dtc/srcpos.h
 create mode 100644 util_lib/dtc/util.c
 create mode 100644 util_lib/dtc/util.h
 create mode 100644 util_lib/dtc/version_gen.h

diff --git a/util_lib/Makefile b/util_lib/Makefile
index 54ccdc5..8b00944 100644
--- a/util_lib/Makefile
+++ b/util_lib/Makefile
@@ -1,6 +1,8 @@
 #
 # Utility function library
 #
+include $(srcdir)/util_lib/dtc/Makefile.dtc
+
 UTIL_LIB_SRCS +=
 UTIL_LIB_SRCS += util_lib/compute_ip_checksum.c
 UTIL_LIB_SRCS += util_lib/sha256.c
diff --git a/util_lib/dtc/Makefile.dtc b/util_lib/dtc/Makefile.dtc
new file mode 100644
index 0000000..3433d76
--- /dev/null
+++ b/util_lib/dtc/Makefile.dtc
@@ -0,0 +1,9 @@
+DTC_INCLUDES = dtc.h srcpos.h util.h version_gen.h
+DTC_SRCS = fstree.c flattree.c srcpos.c util.c livetree.c data.c dtc.c
+DTC_OBJS = $(DTC_SRCS:%.c=%.o)
+
+CPPFLAGS += -I$(srcdir)/util_lib/dtc/
+
+dist += util_lib/dtc/Makefile.dtc \
+        $(DTC_SRCS:%=util_lib/dtc/%) \
+        $(DTC_INCLUDES:%=util_lib/dtc/%)
\ No newline at end of file
diff --git a/util_lib/dtc/data.c b/util_lib/dtc/data.c
new file mode 100644
index 0000000..fe555e8
--- /dev/null
+++ b/util_lib/dtc/data.c
@@ -0,0 +1,321 @@
+/*
+ * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+
+void data_free(struct data d)
+{
+	struct marker *m, *nm;
+
+	m = d.markers;
+	while (m) {
+		nm = m->next;
+		free(m->ref);
+		free(m);
+		m = nm;
+	}
+
+	if (d.val)
+		free(d.val);
+}
+
+struct data data_grow_for(struct data d, int xlen)
+{
+	struct data nd;
+	int newsize;
+
+	if (xlen == 0)
+		return d;
+
+	nd = d;
+
+	newsize = xlen;
+
+	while ((d.len + xlen) > newsize)
+		newsize *= 2;
+
+	nd.val = xrealloc(d.val, newsize);
+
+	return nd;
+}
+
+struct data data_copy_mem(const char *mem, int len)
+{
+	struct data d;
+
+	d = data_grow_for(empty_data, len);
+
+	d.len = len;
+	memcpy(d.val, mem, len);
+
+	return d;
+}
+
+static char get_oct_char(const char *s, int *i)
+{
+	char x[4];
+	char *endx;
+	long val;
+
+	x[3] = '\0';
+	strncpy(x, s + *i, 3);
+
+	val = strtol(x, &endx, 8);
+
+	assert(endx > x);
+
+	(*i) += endx - x;
+	return val;
+}
+
+static char get_hex_char(const char *s, int *i)
+{
+	char x[3];
+	char *endx;
+	long val;
+
+	x[2] = '\0';
+	strncpy(x, s + *i, 2);
+
+	val = strtol(x, &endx, 16);
+	if (!(endx  > x))
+		die("\\x used with no following hex digits\n");
+
+	(*i) += endx - x;
+	return val;
+}
+
+struct data data_copy_escape_string(const char *s, int len)
+{
+	int i = 0;
+	struct data d;
+	char *q;
+
+	d = data_grow_for(empty_data, strlen(s)+1);
+
+	q = d.val;
+	while (i < len) {
+		char c = s[i++];
+
+		if (c != '\\') {
+			q[d.len++] = c;
+			continue;
+		}
+
+		c = s[i++];
+		assert(c);
+		switch (c) {
+		case 'a':
+			q[d.len++] = '\a';
+			break;
+		case 'b':
+			q[d.len++] = '\b';
+			break;
+		case 't':
+			q[d.len++] = '\t';
+			break;
+		case 'n':
+			q[d.len++] = '\n';
+			break;
+		case 'v':
+			q[d.len++] = '\v';
+			break;
+		case 'f':
+			q[d.len++] = '\f';
+			break;
+		case 'r':
+			q[d.len++] = '\r';
+			break;
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+			i--; /* need to re-read the first digit as
+			      * part of the octal value */
+			q[d.len++] = get_oct_char(s, &i);
+			break;
+		case 'x':
+			q[d.len++] = get_hex_char(s, &i);
+			break;
+		default:
+			q[d.len++] = c;
+		}
+	}
+
+	q[d.len++] = '\0';
+	return d;
+}
+
+struct data data_copy_file(FILE *f, size_t maxlen)
+{
+	struct data d = empty_data;
+
+	while (!feof(f) && (d.len < maxlen)) {
+		size_t chunksize, ret;
+
+		if (maxlen == -1)
+			chunksize = 4096;
+		else
+			chunksize = maxlen - d.len;
+
+		d = data_grow_for(d, chunksize);
+		ret = fread(d.val + d.len, 1, chunksize, f);
+
+		if (ferror(f))
+			die("Error reading file into data: %s", strerror(errno));
+
+		if (d.len + ret < d.len)
+			die("Overflow reading file into data\n");
+
+		d.len += ret;
+	}
+
+	return d;
+}
+
+struct data data_append_data(struct data d, const void *p, int len)
+{
+	d = data_grow_for(d, len);
+	memcpy(d.val + d.len, p, len);
+	d.len += len;
+	return d;
+}
+
+struct data data_insert_at_marker(struct data d, struct marker *m,
+				  const void *p, int len)
+{
+	d = data_grow_for(d, len);
+	memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset);
+	memcpy(d.val + m->offset, p, len);
+	d.len += len;
+
+	/* Adjust all markers after the one we're inserting at */
+	m = m->next;
+	for_each_marker(m)
+		m->offset += len;
+	return d;
+}
+
+static struct data data_append_markers(struct data d, struct marker *m)
+{
+	struct marker **mp = &d.markers;
+
+	/* Find the end of the markerlist */
+	while (*mp)
+		mp = &((*mp)->next);
+	*mp = m;
+	return d;
+}
+
+struct data data_merge(struct data d1, struct data d2)
+{
+	struct data d;
+	struct marker *m2 = d2.markers;
+
+	d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
+
+	/* Adjust for the length of d1 */
+	for_each_marker(m2)
+		m2->offset += d1.len;
+
+	d2.markers = NULL; /* So data_free() doesn't clobber them */
+	data_free(d2);
+
+	return d;
+}
+
+struct data data_append_cell(struct data d, cell_t word)
+{
+	cell_t beword = cpu_to_fdt32(word);
+
+	return data_append_data(d, &beword, sizeof(beword));
+}
+
+struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
+{
+	struct fdt_reserve_entry bere;
+
+	bere.address = cpu_to_fdt64(re->address);
+	bere.size = cpu_to_fdt64(re->size);
+
+	return data_append_data(d, &bere, sizeof(bere));
+}
+
+struct data data_append_addr(struct data d, uint64_t addr)
+{
+	uint64_t beaddr = cpu_to_fdt64(addr);
+
+	return data_append_data(d, &beaddr, sizeof(beaddr));
+}
+
+struct data data_append_byte(struct data d, uint8_t byte)
+{
+	return data_append_data(d, &byte, 1);
+}
+
+struct data data_append_zeroes(struct data d, int len)
+{
+	d = data_grow_for(d, len);
+
+	memset(d.val + d.len, 0, len);
+	d.len += len;
+	return d;
+}
+
+struct data data_append_align(struct data d, int align)
+{
+	int newlen = ALIGN(d.len, align);
+	return data_append_zeroes(d, newlen - d.len);
+}
+
+struct data data_add_marker(struct data d, enum markertype type, char *ref)
+{
+	struct marker *m;
+
+	m = xmalloc(sizeof(*m));
+	m->offset = d.len;
+	m->type = type;
+	m->ref = ref;
+	m->next = NULL;
+
+	return data_append_markers(d, m);
+}
+
+int data_is_one_string(struct data d)
+{
+	int i;
+	int len = d.len;
+
+	if (len == 0)
+		return 0;
+
+	for (i = 0; i < len-1; i++)
+		if (d.val[i] == '\0')
+			return 0;
+
+	if (d.val[len-1] != '\0')
+		return 0;
+
+	return 1;
+}
diff --git a/util_lib/dtc/dtc.c b/util_lib/dtc/dtc.c
new file mode 100644
index 0000000..b812dfc
--- /dev/null
+++ b/util_lib/dtc/dtc.c
@@ -0,0 +1,44 @@
+/*
+ * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+#include "srcpos.h"
+
+#include "version_gen.h"
+
+static void fill_fullpaths(struct node *tree, const char *prefix)
+{
+	struct node *child;
+	const char *unit;
+
+	tree->fullpath = join_path(prefix, tree->name);
+
+	unit = strchr(tree->name, '@');
+	if (unit)
+		tree->basenamelen = unit - tree->name;
+	else
+		tree->basenamelen = strlen(tree->name);
+
+	for_each_child(tree, child)
+		fill_fullpaths(child, tree->fullpath);
+}
+
+
+
diff --git a/util_lib/dtc/dtc.h b/util_lib/dtc/dtc.h
new file mode 100644
index 0000000..afb26f6
--- /dev/null
+++ b/util_lib/dtc/dtc.h
@@ -0,0 +1,244 @@
+#ifndef _DTC_H
+#define _DTC_H
+
+/*
+ * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <libfdt_env.h>
+#include <fdt.h>
+
+#include "util.h"
+
+#ifdef DEBUG
+#define debug(fmt,args...)	printf(fmt, ##args)
+#else
+#define debug(fmt,args...)
+#endif
+
+
+#define DEFAULT_FDT_VERSION	17
+
+/*
+ * Command line options
+ */
+extern int quiet;		/* Level of quietness */
+extern int reservenum;		/* Number of memory reservation slots */
+extern int minsize;		/* Minimum blob size */
+extern int padsize;		/* Additional padding to blob */
+extern int phandle_format;	/* Use linux,phandle or phandle properties */
+
+#define PHANDLE_LEGACY	0x1
+#define PHANDLE_EPAPR	0x2
+#define PHANDLE_BOTH	0x3
+
+typedef uint32_t cell_t;
+
+
+#define streq(a, b)	(strcmp((a), (b)) == 0)
+#define strneq(a, b, n)	(strncmp((a), (b), (n)) == 0)
+
+#define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/* Data blobs */
+enum markertype {
+	REF_PHANDLE,
+	REF_PATH,
+	LABEL,
+};
+
+struct  marker {
+	enum markertype type;
+	int offset;
+	char *ref;
+	struct marker *next;
+};
+
+struct data {
+	int len;
+	char *val;
+	struct marker *markers;
+};
+
+
+#define empty_data ((struct data){ /* all .members = 0 or NULL */ })
+
+#define for_each_marker(m) \
+	for (; (m); (m) = (m)->next)
+#define for_each_marker_of_type(m, t) \
+	for_each_marker(m) \
+		if ((m)->type == (t))
+
+void data_free(struct data d);
+
+struct data data_grow_for(struct data d, int xlen);
+
+struct data data_copy_mem(const char *mem, int len);
+struct data data_copy_escape_string(const char *s, int len);
+struct data data_copy_file(FILE *f, size_t len);
+
+struct data data_append_data(struct data d, const void *p, int len);
+struct data data_insert_at_marker(struct data d, struct marker *m,
+				  const void *p, int len);
+struct data data_merge(struct data d1, struct data d2);
+struct data data_append_cell(struct data d, cell_t word);
+struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
+struct data data_append_addr(struct data d, uint64_t addr);
+struct data data_append_byte(struct data d, uint8_t byte);
+struct data data_append_zeroes(struct data d, int len);
+struct data data_append_align(struct data d, int align);
+
+struct data data_add_marker(struct data d, enum markertype type, char *ref);
+
+int data_is_one_string(struct data d);
+
+/* DT constraints */
+
+#define MAX_PROPNAME_LEN	31
+#define MAX_NODENAME_LEN	31
+
+/* Live trees */
+struct label {
+	char *label;
+	struct label *next;
+};
+
+struct property {
+	char *name;
+	struct data val;
+
+	struct property *next;
+
+	struct label *labels;
+};
+
+struct node {
+	char *name;
+	struct property *proplist;
+	struct node *children;
+
+	struct node *parent;
+	struct node *next_sibling;
+
+	char *fullpath;
+	int basenamelen;
+
+	cell_t phandle;
+	int addr_cells, size_cells;
+
+	struct label *labels;
+};
+
+#define for_each_label(l0, l) \
+	for ((l) = (l0); (l); (l) = (l)->next)
+
+#define for_each_property(n, p) \
+	for ((p) = (n)->proplist; (p); (p) = (p)->next)
+
+#define for_each_child(n, c)	\
+	for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
+
+void add_label(struct label **labels, char *label);
+
+struct property *build_property(char *name, struct data val);
+struct property *chain_property(struct property *first, struct property *list);
+struct property *reverse_properties(struct property *first);
+
+struct node *build_node(struct property *proplist, struct node *children);
+struct node *name_node(struct node *node, char *name);
+struct node *chain_node(struct node *first, struct node *list);
+struct node *merge_nodes(struct node *old_node, struct node *new_node);
+
+void add_property(struct node *node, struct property *prop);
+void add_child(struct node *parent, struct node *child);
+
+const char *get_unitname(struct node *node);
+struct property *get_property(struct node *node, const char *propname);
+cell_t propval_cell(struct property *prop);
+struct property *get_property_by_label(struct node *tree, const char *label,
+				       struct node **node);
+struct marker *get_marker_label(struct node *tree, const char *label,
+				struct node **node, struct property **prop);
+struct node *get_subnode(struct node *node, const char *nodename);
+struct node *get_node_by_path(struct node *tree, const char *path);
+struct node *get_node_by_label(struct node *tree, const char *label);
+struct node *get_node_by_phandle(struct node *tree, cell_t phandle);
+struct node *get_node_by_ref(struct node *tree, const char *ref);
+cell_t get_node_phandle(struct node *root, struct node *node);
+
+uint32_t guess_boot_cpuid(struct node *tree);
+
+/* Boot info (tree plus memreserve information */
+
+struct reserve_info {
+	struct fdt_reserve_entry re;
+
+	struct reserve_info *next;
+
+	struct label *labels;
+};
+
+struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len);
+struct reserve_info *chain_reserve_entry(struct reserve_info *first,
+					 struct reserve_info *list);
+struct reserve_info *add_reserve_entry(struct reserve_info *list,
+				       struct reserve_info *new);
+
+
+struct boot_info {
+	struct reserve_info *reservelist;
+	struct node *dt;		/* the device tree */
+	uint32_t boot_cpuid_phys;
+};
+
+struct boot_info *build_boot_info(struct reserve_info *reservelist,
+				  struct node *tree, uint32_t boot_cpuid_phys);
+void sort_tree(struct boot_info *bi);
+
+/* Checks */
+
+void process_checks(int force, struct boot_info *bi);
+
+/* Flattened trees */
+
+void* dt_to_blob_buf(off_t* size, struct boot_info *bi, int version);
+
+struct boot_info *dt_from_blob(const char *fname);
+
+/* Tree source */
+
+void dt_to_source(FILE *f, struct boot_info *bi);
+struct boot_info *dt_from_source(const char *f);
+
+/* FS trees */
+
+struct boot_info *dt_from_fs(const char *dirname);
+
+#endif /* _DTC_H */
diff --git a/util_lib/dtc/flattree.c b/util_lib/dtc/flattree.c
new file mode 100644
index 0000000..d110001
--- /dev/null
+++ b/util_lib/dtc/flattree.c
@@ -0,0 +1,649 @@
+/*
+ * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+#include "srcpos.h"
+
+#define FTF_FULLPATH	0x1
+#define FTF_VARALIGN	0x2
+#define FTF_NAMEPROPS	0x4
+#define FTF_BOOTCPUID	0x8
+#define FTF_STRTABSIZE	0x10
+#define FTF_STRUCTSIZE	0x20
+#define FTF_NOPS	0x40
+
+static struct version_info {
+	int version;
+	int last_comp_version;
+	int hdr_size;
+	int flags;
+} version_table[] = {
+	{1, 1, FDT_V1_SIZE,
+	 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS},
+	{2, 1, FDT_V2_SIZE,
+	 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID},
+	{3, 1, FDT_V3_SIZE,
+	 FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE},
+	{16, 16, FDT_V3_SIZE,
+	 FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS},
+	{17, 16, FDT_V17_SIZE,
+	 FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS},
+};
+
+struct emitter {
+	void (*cell)(void *, cell_t);
+	void (*string)(void *, char *, int);
+	void (*align)(void *, int);
+	void (*data)(void *, struct data);
+	void (*beginnode)(void *, struct label *labels);
+	void (*endnode)(void *, struct label *labels);
+	void (*property)(void *, struct label *labels);
+};
+
+static void bin_emit_cell(void *e, cell_t val)
+{
+	struct data *dtbuf = e;
+
+	*dtbuf = data_append_cell(*dtbuf, val);
+}
+
+static void bin_emit_string(void *e, char *str, int len)
+{
+	struct data *dtbuf = e;
+
+	if (len == 0)
+		len = strlen(str);
+
+	*dtbuf = data_append_data(*dtbuf, str, len);
+	*dtbuf = data_append_byte(*dtbuf, '\0');
+}
+
+static void bin_emit_align(void *e, int a)
+{
+	struct data *dtbuf = e;
+
+	*dtbuf = data_append_align(*dtbuf, a);
+}
+
+static void bin_emit_data(void *e, struct data d)
+{
+	struct data *dtbuf = e;
+
+	*dtbuf = data_append_data(*dtbuf, d.val, d.len);
+}
+
+static void bin_emit_beginnode(void *e, struct label *labels)
+{
+	bin_emit_cell(e, FDT_BEGIN_NODE);
+}
+
+static void bin_emit_endnode(void *e, struct label *labels)
+{
+	bin_emit_cell(e, FDT_END_NODE);
+}
+
+static void bin_emit_property(void *e, struct label *labels)
+{
+	bin_emit_cell(e, FDT_PROP);
+}
+
+static struct emitter bin_emitter = {
+	.cell = bin_emit_cell,
+	.string = bin_emit_string,
+	.align = bin_emit_align,
+	.data = bin_emit_data,
+	.beginnode = bin_emit_beginnode,
+	.endnode = bin_emit_endnode,
+	.property = bin_emit_property,
+};
+
+
+#define ASM_EMIT_BELONG(f, fmt, ...) \
+	{ \
+		fprintf((f), "\t.byte\t((" fmt ") >> 24) & 0xff\n", __VA_ARGS__); \
+		fprintf((f), "\t.byte\t((" fmt ") >> 16) & 0xff\n", __VA_ARGS__); \
+		fprintf((f), "\t.byte\t((" fmt ") >> 8) & 0xff\n", __VA_ARGS__); \
+		fprintf((f), "\t.byte\t(" fmt ") & 0xff\n", __VA_ARGS__); \
+	}
+
+
+
+
+static int stringtable_insert(struct data *d, const char *str)
+{
+	int i;
+
+	/* FIXME: do this more efficiently? */
+
+	for (i = 0; i < d->len; i++) {
+		if (streq(str, d->val + i))
+			return i;
+	}
+
+	*d = data_append_data(*d, str, strlen(str)+1);
+	return i;
+}
+
+static void flatten_tree(struct node *tree, struct emitter *emit,
+			 void *etarget, struct data *strbuf,
+			 struct version_info *vi)
+{
+	struct property *prop;
+	struct node *child;
+	int seen_name_prop = 0;
+
+	emit->beginnode(etarget, tree->labels);
+
+	if (vi->flags & FTF_FULLPATH)
+		emit->string(etarget, tree->fullpath, 0);
+	else
+		emit->string(etarget, tree->name, 0);
+
+	emit->align(etarget, sizeof(cell_t));
+
+	for_each_property(tree, prop) {
+		int nameoff;
+
+		if (streq(prop->name, "name"))
+			seen_name_prop = 1;
+
+		nameoff = stringtable_insert(strbuf, prop->name);
+
+		emit->property(etarget, prop->labels);
+		emit->cell(etarget, prop->val.len);
+		emit->cell(etarget, nameoff);
+
+		if ((vi->flags & FTF_VARALIGN) && (prop->val.len >= 8))
+			emit->align(etarget, 8);
+
+		emit->data(etarget, prop->val);
+		emit->align(etarget, sizeof(cell_t));
+	}
+
+	if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) {
+		emit->property(etarget, NULL);
+		emit->cell(etarget, tree->basenamelen+1);
+		emit->cell(etarget, stringtable_insert(strbuf, "name"));
+
+		if ((vi->flags & FTF_VARALIGN) && ((tree->basenamelen+1) >= 8))
+			emit->align(etarget, 8);
+
+		emit->string(etarget, tree->name, tree->basenamelen);
+		emit->align(etarget, sizeof(cell_t));
+	}
+
+	for_each_child(tree, child) {
+		flatten_tree(child, emit, etarget, strbuf, vi);
+	}
+
+	emit->endnode(etarget, tree->labels);
+}
+
+static struct data flatten_reserve_list(struct reserve_info *reservelist,
+				 struct version_info *vi)
+{
+	struct reserve_info *re;
+	struct data d = empty_data;
+
+	for (re = reservelist; re; re = re->next) {
+		d = data_append_re(d, &re->re);
+	}
+
+	return d;
+}
+
+static void make_fdt_header(struct fdt_header *fdt,
+			    struct version_info *vi,
+			    int reservesize, int dtsize, int strsize,
+			    int boot_cpuid_phys)
+{
+	int reserve_off;
+
+	reservesize += sizeof(struct fdt_reserve_entry);
+
+	memset(fdt, 0xff, sizeof(*fdt));
+
+	fdt->magic = cpu_to_fdt32(FDT_MAGIC);
+	fdt->version = cpu_to_fdt32(vi->version);
+	fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version);
+
+	/* Reserve map should be doubleword aligned */
+	reserve_off = ALIGN(vi->hdr_size, 8);
+
+	fdt->off_mem_rsvmap = cpu_to_fdt32(reserve_off);
+	fdt->off_dt_struct = cpu_to_fdt32(reserve_off + reservesize);
+	fdt->off_dt_strings = cpu_to_fdt32(reserve_off + reservesize
+					  + dtsize);
+	fdt->totalsize = cpu_to_fdt32(reserve_off + reservesize + dtsize + strsize);
+
+	if (vi->flags & FTF_BOOTCPUID)
+		fdt->boot_cpuid_phys = cpu_to_fdt32(boot_cpuid_phys);
+	if (vi->flags & FTF_STRTABSIZE)
+		fdt->size_dt_strings = cpu_to_fdt32(strsize);
+	if (vi->flags & FTF_STRUCTSIZE)
+		fdt->size_dt_struct = cpu_to_fdt32(dtsize);
+}
+
+void* dt_to_blob_buf(off_t* size, struct boot_info *bi, int version)
+{
+	struct version_info *vi = NULL;
+	int i;
+	struct data blob       = empty_data;
+	struct data reservebuf = empty_data;
+	struct data dtbuf      = empty_data;
+	struct data strbuf     = empty_data;
+	struct fdt_header fdt;
+	int padlen = 0;
+
+	for (i = 0; i < ARRAY_SIZE(version_table); i++) {
+		if (version_table[i].version == version)
+			vi = &version_table[i];
+	}
+
+	if (!vi)
+		die("Unknown device tree blob version %d\n", version);
+
+	flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi);
+	bin_emit_cell(&dtbuf, FDT_END);
+
+	reservebuf = flatten_reserve_list(bi->reservelist, vi);
+
+	/* Make header */
+	make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
+			bi->boot_cpuid_phys);
+
+	if (padlen > 0) {
+		int tsize = fdt32_to_cpu(fdt.totalsize);
+		tsize += padlen;
+		fdt.totalsize = cpu_to_fdt32(tsize);
+	}
+
+	/*
+	 * Assemble the blob: start with the header, add with alignment
+	 * the reserve buffer, add the reserve map terminating zeroes,
+	 * the device tree itself, and finally the strings.
+	 */
+	blob = data_append_data(blob, &fdt, vi->hdr_size);
+	blob = data_append_align(blob, 8);
+	blob = data_merge(blob, reservebuf);
+	blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry));
+	blob = data_merge(blob, dtbuf);
+	blob = data_merge(blob, strbuf);
+
+	*size = blob.len;
+
+	return blob.val;
+}
+
+
+struct inbuf {
+	char *base, *limit, *ptr;
+};
+
+static void inbuf_init(struct inbuf *inb, void *base, void *limit)
+{
+	inb->base = base;
+	inb->limit = limit;
+	inb->ptr = inb->base;
+}
+
+static void flat_read_chunk(struct inbuf *inb, void *p, int len)
+{
+	if ((inb->ptr + len) > inb->limit)
+		die("Premature end of data parsing flat device tree\n");
+
+	memcpy(p, inb->ptr, len);
+
+	inb->ptr += len;
+}
+
+static uint32_t flat_read_word(struct inbuf *inb)
+{
+	uint32_t val;
+
+	assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
+
+	flat_read_chunk(inb, &val, sizeof(val));
+
+	return fdt32_to_cpu(val);
+}
+
+static void flat_realign(struct inbuf *inb, int align)
+{
+	int off = inb->ptr - inb->base;
+
+	inb->ptr = inb->base + ALIGN(off, align);
+	if (inb->ptr > inb->limit)
+		die("Premature end of data parsing flat device tree\n");
+}
+
+static char *flat_read_string(struct inbuf *inb)
+{
+	int len = 0;
+	const char *p = inb->ptr;
+	char *str;
+
+	do {
+		if (p >= inb->limit)
+			die("Premature end of data parsing flat device tree\n");
+		len++;
+	} while ((*p++) != '\0');
+
+	str = xstrdup(inb->ptr);
+
+	inb->ptr += len;
+
+	flat_realign(inb, sizeof(uint32_t));
+
+	return str;
+}
+
+static struct data flat_read_data(struct inbuf *inb, int len)
+{
+	struct data d = empty_data;
+
+	if (len == 0)
+		return empty_data;
+
+	d = data_grow_for(d, len);
+	d.len = len;
+
+	flat_read_chunk(inb, d.val, len);
+
+	flat_realign(inb, sizeof(uint32_t));
+
+	return d;
+}
+
+static char *flat_read_stringtable(struct inbuf *inb, int offset)
+{
+	const char *p;
+
+	p = inb->base + offset;
+	while (1) {
+		if (p >= inb->limit || p < inb->base)
+			die("String offset %d overruns string table\n",
+			    offset);
+
+		if (*p == '\0')
+			break;
+
+		p++;
+	}
+
+	return xstrdup(inb->base + offset);
+}
+
+static struct property *flat_read_property(struct inbuf *dtbuf,
+					   struct inbuf *strbuf, int flags)
+{
+	uint32_t proplen, stroff;
+	char *name;
+	struct data val;
+
+	proplen = flat_read_word(dtbuf);
+	stroff = flat_read_word(dtbuf);
+
+	name = flat_read_stringtable(strbuf, stroff);
+
+	if ((flags & FTF_VARALIGN) && (proplen >= 8))
+		flat_realign(dtbuf, 8);
+
+	val = flat_read_data(dtbuf, proplen);
+
+	return build_property(name, val);
+}
+
+
+static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
+{
+	struct reserve_info *reservelist = NULL;
+	struct reserve_info *new;
+	struct fdt_reserve_entry re;
+
+	/*
+	 * Each entry is a pair of u64 (addr, size) values for 4 cell_t's.
+	 * List terminates at an entry with size equal to zero.
+	 *
+	 * First pass, count entries.
+	 */
+	while (1) {
+		flat_read_chunk(inb, &re, sizeof(re));
+		re.address  = fdt64_to_cpu(re.address);
+		re.size = fdt64_to_cpu(re.size);
+		if (re.size == 0)
+			break;
+
+		new = build_reserve_entry(re.address, re.size);
+		reservelist = add_reserve_entry(reservelist, new);
+	}
+
+	return reservelist;
+}
+
+
+static char *nodename_from_path(const char *ppath, const char *cpath)
+{
+	int plen;
+
+	plen = strlen(ppath);
+
+	if (!strneq(ppath, cpath, plen))
+		die("Path \"%s\" is not valid as a child of \"%s\"\n",
+		    cpath, ppath);
+
+	/* root node is a special case */
+	if (!streq(ppath, "/"))
+		plen++;
+
+	return xstrdup(cpath + plen);
+}
+
+static struct node *unflatten_tree(struct inbuf *dtbuf,
+				   struct inbuf *strbuf,
+				   const char *parent_flatname, int flags)
+{
+	struct node *node;
+	char *flatname;
+	uint32_t val;
+
+	node = build_node(NULL, NULL);
+
+	flatname = flat_read_string(dtbuf);
+
+	if (flags & FTF_FULLPATH)
+		node->name = nodename_from_path(parent_flatname, flatname);
+	else
+		node->name = flatname;
+
+	do {
+		struct property *prop;
+		struct node *child;
+
+		val = flat_read_word(dtbuf);
+		switch (val) {
+		case FDT_PROP:
+			if (node->children)
+				fprintf(stderr, "Warning: Flat tree input has "
+					"subnodes preceding a property.\n");
+			prop = flat_read_property(dtbuf, strbuf, flags);
+			add_property(node, prop);
+			break;
+
+		case FDT_BEGIN_NODE:
+			child = unflatten_tree(dtbuf,strbuf, flatname, flags);
+			add_child(node, child);
+			break;
+
+		case FDT_END_NODE:
+			break;
+
+		case FDT_END:
+			die("Premature FDT_END in device tree blob\n");
+			break;
+
+		case FDT_NOP:
+			if (!(flags & FTF_NOPS))
+				fprintf(stderr, "Warning: NOP tag found in flat tree"
+					" version <16\n");
+
+			/* Ignore */
+			break;
+
+		default:
+			die("Invalid opcode word %08x in device tree blob\n",
+			    val);
+		}
+	} while (val != FDT_END_NODE);
+
+	return node;
+}
+
+
+struct boot_info *dt_from_blob(const char *fname)
+{
+	FILE *f;
+	uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
+	uint32_t off_dt, off_str, off_mem_rsvmap;
+	int rc;
+	char *blob;
+	struct fdt_header *fdt;
+	char *p;
+	struct inbuf dtbuf, strbuf;
+	struct inbuf memresvbuf;
+	int sizeleft;
+	struct reserve_info *reservelist;
+	struct node *tree;
+	uint32_t val;
+	int flags = 0;
+
+	f = srcfile_relative_open(fname, NULL);
+
+	rc = fread(&magic, sizeof(magic), 1, f);
+	if (ferror(f))
+		die("Error reading DT blob magic number: %s\n",
+		    strerror(errno));
+	if (rc < 1) {
+		if (feof(f))
+			die("EOF reading DT blob magic number\n");
+		else
+			die("Mysterious short read reading magic number\n");
+	}
+
+	magic = fdt32_to_cpu(magic);
+	if (magic != FDT_MAGIC)
+		die("Blob has incorrect magic number\n");
+
+	rc = fread(&totalsize, sizeof(totalsize), 1, f);
+	if (ferror(f))
+		die("Error reading DT blob size: %s\n", strerror(errno));
+	if (rc < 1) {
+		if (feof(f))
+			die("EOF reading DT blob size\n");
+		else
+			die("Mysterious short read reading blob size\n");
+	}
+
+	totalsize = fdt32_to_cpu(totalsize);
+	if (totalsize < FDT_V1_SIZE)
+		die("DT blob size (%d) is too small\n", totalsize);
+
+	blob = xmalloc(totalsize);
+
+	fdt = (struct fdt_header *)blob;
+	fdt->magic = cpu_to_fdt32(magic);
+	fdt->totalsize = cpu_to_fdt32(totalsize);
+
+	sizeleft = totalsize - sizeof(magic) - sizeof(totalsize);
+	p = blob + sizeof(magic)  + sizeof(totalsize);
+
+	while (sizeleft) {
+		if (feof(f))
+			die("EOF before reading %d bytes of DT blob\n",
+			    totalsize);
+
+		rc = fread(p, 1, sizeleft, f);
+		if (ferror(f))
+			die("Error reading DT blob: %s\n",
+			    strerror(errno));
+
+		sizeleft -= rc;
+		p += rc;
+	}
+
+	off_dt = fdt32_to_cpu(fdt->off_dt_struct);
+	off_str = fdt32_to_cpu(fdt->off_dt_strings);
+	off_mem_rsvmap = fdt32_to_cpu(fdt->off_mem_rsvmap);
+	version = fdt32_to_cpu(fdt->version);
+	boot_cpuid_phys = fdt32_to_cpu(fdt->boot_cpuid_phys);
+
+	if (off_mem_rsvmap >= totalsize)
+		die("Mem Reserve structure offset exceeds total size\n");
+
+	if (off_dt >= totalsize)
+		die("DT structure offset exceeds total size\n");
+
+	if (off_str > totalsize)
+		die("String table offset exceeds total size\n");
+
+	if (version >= 3) {
+		uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
+		if (off_str+size_str > totalsize)
+			die("String table extends past total size\n");
+		inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
+	} else {
+		inbuf_init(&strbuf, blob + off_str, blob + totalsize);
+	}
+
+	if (version >= 17) {
+		size_dt = fdt32_to_cpu(fdt->size_dt_struct);
+		if (off_dt+size_dt > totalsize)
+			die("Structure block extends past total size\n");
+	}
+
+	if (version < 16) {
+		flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN;
+	} else {
+		flags |= FTF_NOPS;
+	}
+
+	inbuf_init(&memresvbuf,
+		   blob + off_mem_rsvmap, blob + totalsize);
+	inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
+
+	reservelist = flat_read_mem_reserve(&memresvbuf);
+
+	val = flat_read_word(&dtbuf);
+
+	if (val != FDT_BEGIN_NODE)
+		die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val);
+
+	tree = unflatten_tree(&dtbuf, &strbuf, "", flags);
+
+	val = flat_read_word(&dtbuf);
+	if (val != FDT_END)
+		die("Device tree blob doesn't end with FDT_END\n");
+
+	free(blob);
+
+	fclose(f);
+
+	return build_boot_info(reservelist, tree, boot_cpuid_phys);
+}
diff --git a/util_lib/dtc/fstree.c b/util_lib/dtc/fstree.c
new file mode 100644
index 0000000..f377453
--- /dev/null
+++ b/util_lib/dtc/fstree.c
@@ -0,0 +1,91 @@
+/*
+ * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+
+static struct node *read_fstree(const char *dirname)
+{
+	DIR *d;
+	struct dirent *de;
+	struct stat st;
+	struct node *tree;
+
+	d = opendir(dirname);
+	if (!d)
+		die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
+
+	tree = build_node(NULL, NULL);
+
+	while ((de = readdir(d)) != NULL) {
+		char *tmpnam;
+
+		if (streq(de->d_name, ".")
+		    || streq(de->d_name, ".."))
+			continue;
+
+		tmpnam = join_path(dirname, de->d_name);
+
+		if (lstat(tmpnam, &st) < 0)
+			die("stat(%s): %s\n", tmpnam, strerror(errno));
+
+		if (S_ISREG(st.st_mode)) {
+			struct property *prop;
+			FILE *pfile;
+
+			pfile = fopen(tmpnam, "r");
+			if (! pfile) {
+				fprintf(stderr,
+					"WARNING: Cannot open %s: %s\n",
+					tmpnam, strerror(errno));
+			} else {
+				prop = build_property(xstrdup(de->d_name),
+						      data_copy_file(pfile,
+								     st.st_size));
+				add_property(tree, prop);
+				fclose(pfile);
+			}
+		} else if (S_ISDIR(st.st_mode)) {
+			struct node *newchild;
+
+			newchild = read_fstree(tmpnam);
+			newchild = name_node(newchild, xstrdup(de->d_name));
+			add_child(tree, newchild);
+		}
+
+		free(tmpnam);
+	}
+
+	closedir(d);
+	return tree;
+}
+
+struct boot_info *dt_from_fs(const char *dirname)
+{
+	struct node *tree;
+
+	tree = read_fstree(dirname);
+	tree = name_node(tree, "");
+
+	return build_boot_info(NULL, tree, guess_boot_cpuid(tree));
+}
+
diff --git a/util_lib/dtc/livetree.c b/util_lib/dtc/livetree.c
new file mode 100644
index 0000000..1420804
--- /dev/null
+++ b/util_lib/dtc/livetree.c
@@ -0,0 +1,579 @@
+/*
+ * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
+ *
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include "dtc.h"
+
+/*
+ * Tree building functions
+ */
+
+void add_label(struct label **labels, char *label)
+{
+	struct label *new;
+
+	/* Make sure the label isn't already there */
+	for_each_label(*labels, new)
+		if (streq(new->label, label))
+			return;
+
+	new = xmalloc(sizeof(*new));
+	new->label = label;
+	new->next = *labels;
+	*labels = new;
+}
+
+struct property *build_property(char *name, struct data val)
+{
+	struct property *new = xmalloc(sizeof(*new));
+
+	memset(new, 0, sizeof(*new));
+
+	new->name = name;
+	new->val = val;
+
+	return new;
+}
+
+struct property *chain_property(struct property *first, struct property *list)
+{
+	assert(first->next == NULL);
+
+	first->next = list;
+	return first;
+}
+
+struct property *reverse_properties(struct property *first)
+{
+	struct property *p = first;
+	struct property *head = NULL;
+	struct property *next;
+
+	while (p) {
+		next = p->next;
+		p->next = head;
+		head = p;
+		p = next;
+	}
+	return head;
+}
+
+struct node *build_node(struct property *proplist, struct node *children)
+{
+	struct node *new = xmalloc(sizeof(*new));
+	struct node *child;
+
+	memset(new, 0, sizeof(*new));
+
+	new->proplist = reverse_properties(proplist);
+	new->children = children;
+
+	for_each_child(new, child) {
+		child->parent = new;
+	}
+
+	return new;
+}
+
+struct node *name_node(struct node *node, char *name)
+{
+	assert(node->name == NULL);
+
+	node->name = name;
+
+	return node;
+}
+
+struct node *merge_nodes(struct node *old_node, struct node *new_node)
+{
+	struct property *new_prop, *old_prop;
+	struct node *new_child, *old_child;
+	struct label *l;
+
+	/* Add new node labels to old node */
+	for_each_label(new_node->labels, l)
+		add_label(&old_node->labels, l->label);
+
+	/* Move properties from the new node to the old node.  If there
+	 * is a collision, replace the old value with the new */
+	while (new_node->proplist) {
+		/* Pop the property off the list */
+		new_prop = new_node->proplist;
+		new_node->proplist = new_prop->next;
+		new_prop->next = NULL;
+
+		/* Look for a collision, set new value if there is */
+		for_each_property(old_node, old_prop) {
+			if (streq(old_prop->name, new_prop->name)) {
+				/* Add new labels to old property */
+				for_each_label(new_prop->labels, l)
+					add_label(&old_prop->labels, l->label);
+
+				old_prop->val = new_prop->val;
+				free(new_prop);
+				new_prop = NULL;
+				break;
+			}
+		}
+
+		/* if no collision occurred, add property to the old node. */
+		if (new_prop)
+			add_property(old_node, new_prop);
+	}
+
+	/* Move the override child nodes into the primary node.  If
+	 * there is a collision, then merge the nodes. */
+	while (new_node->children) {
+		/* Pop the child node off the list */
+		new_child = new_node->children;
+		new_node->children = new_child->next_sibling;
+		new_child->parent = NULL;
+		new_child->next_sibling = NULL;
+
+		/* Search for a collision.  Merge if there is */
+		for_each_child(old_node, old_child) {
+			if (streq(old_child->name, new_child->name)) {
+				merge_nodes(old_child, new_child);
+				new_child = NULL;
+				break;
+			}
+		}
+
+		/* if no collision occurred, add child to the old node. */
+		if (new_child)
+			add_child(old_node, new_child);
+	}
+
+	/* The new node contents are now merged into the old node.  Free
+	 * the new node. */
+	free(new_node);
+
+	return old_node;
+}
+
+struct node *chain_node(struct node *first, struct node *list)
+{
+	assert(first->next_sibling == NULL);
+
+	first->next_sibling = list;
+	return first;
+}
+
+void add_property(struct node *node, struct property *prop)
+{
+	struct property **p;
+
+	prop->next = NULL;
+
+	p = &node->proplist;
+	while (*p)
+		p = &((*p)->next);
+
+	*p = prop;
+}
+
+void add_child(struct node *parent, struct node *child)
+{
+	struct node **p;
+
+	child->next_sibling = NULL;
+	child->parent = parent;
+
+	p = &parent->children;
+	while (*p)
+		p = &((*p)->next_sibling);
+
+	*p = child;
+}
+
+struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
+{
+	struct reserve_info *new = xmalloc(sizeof(*new));
+
+	memset(new, 0, sizeof(*new));
+
+	new->re.address = address;
+	new->re.size = size;
+
+	return new;
+}
+
+struct reserve_info *chain_reserve_entry(struct reserve_info *first,
+					struct reserve_info *list)
+{
+	assert(first->next == NULL);
+
+	first->next = list;
+	return first;
+}
+
+struct reserve_info *add_reserve_entry(struct reserve_info *list,
+				      struct reserve_info *new)
+{
+	struct reserve_info *last;
+
+	new->next = NULL;
+
+	if (! list)
+		return new;
+
+	for (last = list; last->next; last = last->next)
+		;
+
+	last->next = new;
+
+	return list;
+}
+
+struct boot_info *build_boot_info(struct reserve_info *reservelist,
+				  struct node *tree, uint32_t boot_cpuid_phys)
+{
+	struct boot_info *bi;
+
+	bi = xmalloc(sizeof(*bi));
+	bi->reservelist = reservelist;
+	bi->dt = tree;
+	bi->boot_cpuid_phys = boot_cpuid_phys;
+
+	return bi;
+}
+
+/*
+ * Tree accessor functions
+ */
+
+const char *get_unitname(struct node *node)
+{
+	if (node->name[node->basenamelen] == '\0')
+		return "";
+	else
+		return node->name + node->basenamelen + 1;
+}
+
+struct property *get_property(struct node *node, const char *propname)
+{
+	struct property *prop;
+
+	for_each_property(node, prop)
+		if (streq(prop->name, propname))
+			return prop;
+
+	return NULL;
+}
+
+cell_t propval_cell(struct property *prop)
+{
+	assert(prop->val.len == sizeof(cell_t));
+	return fdt32_to_cpu(*((cell_t *)prop->val.val));
+}
+
+struct property *get_property_by_label(struct node *tree, const char *label,
+				       struct node **node)
+{
+	struct property *prop;
+	struct node *c;
+
+	*node = tree;
+
+	for_each_property(tree, prop) {
+		struct label *l;
+
+		for_each_label(prop->labels, l)
+			if (streq(l->label, label))
+				return prop;
+	}
+
+	for_each_child(tree, c) {
+		prop = get_property_by_label(c, label, node);
+		if (prop)
+			return prop;
+	}
+
+	*node = NULL;
+	return NULL;
+}
+
+struct marker *get_marker_label(struct node *tree, const char *label,
+				struct node **node, struct property **prop)
+{
+	struct marker *m;
+	struct property *p;
+	struct node *c;
+
+	*node = tree;
+
+	for_each_property(tree, p) {
+		*prop = p;
+		m = p->val.markers;
+		for_each_marker_of_type(m, LABEL)
+			if (streq(m->ref, label))
+				return m;
+	}
+
+	for_each_child(tree, c) {
+		m = get_marker_label(c, label, node, prop);
+		if (m)
+			return m;
+	}
+
+	*prop = NULL;
+	*node = NULL;
+	return NULL;
+}
+
+struct node *get_subnode(struct node *node, const char *nodename)
+{
+	struct node *child;
+
+	for_each_child(node, child)
+		if (streq(child->name, nodename))
+			return child;
+
+	return NULL;
+}
+
+struct node *get_node_by_path(struct node *tree, const char *path)
+{
+	const char *p;
+	struct node *child;
+
+	if (!path || ! (*path))
+		return tree;
+
+	while (path[0] == '/')
+		path++;
+
+	p = strchr(path, '/');
+
+	for_each_child(tree, child) {
+		if (p && strneq(path, child->name, p-path))
+			return get_node_by_path(child, p+1);
+		else if (!p && streq(path, child->name))
+			return child;
+	}
+
+	return NULL;
+}
+
+struct node *get_node_by_label(struct node *tree, const char *label)
+{
+	struct node *child, *node;
+	struct label *l;
+
+	assert(label && (strlen(label) > 0));
+
+	for_each_label(tree->labels, l)
+		if (streq(l->label, label))
+			return tree;
+
+	for_each_child(tree, child) {
+		node = get_node_by_label(child, label);
+		if (node)
+			return node;
+	}
+
+	return NULL;
+}
+
+struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
+{
+	struct node *child, *node;
+
+	assert((phandle != 0) && (phandle != -1));
+
+	if (tree->phandle == phandle)
+		return tree;
+
+	for_each_child(tree, child) {
+		node = get_node_by_phandle(child, phandle);
+		if (node)
+			return node;
+	}
+
+	return NULL;
+}
+
+struct node *get_node_by_ref(struct node *tree, const char *ref)
+{
+	if (ref[0] == '/')
+		return get_node_by_path(tree, ref);
+	else
+		return get_node_by_label(tree, ref);
+}
+
+
+uint32_t guess_boot_cpuid(struct node *tree)
+{
+	struct node *cpus, *bootcpu;
+	struct property *reg;
+
+	cpus = get_node_by_path(tree, "/cpus");
+	if (!cpus)
+		return 0;
+
+
+	bootcpu = cpus->children;
+	if (!bootcpu)
+		return 0;
+
+	reg = get_property(bootcpu, "reg");
+	if (!reg || (reg->val.len != sizeof(uint32_t)))
+		return 0;
+
+	/* FIXME: Sanity check node? */
+
+	return propval_cell(reg);
+}
+
+static int cmp_reserve_info(const void *ax, const void *bx)
+{
+	const struct reserve_info *a, *b;
+
+	a = *((const struct reserve_info * const *)ax);
+	b = *((const struct reserve_info * const *)bx);
+
+	if (a->re.address < b->re.address)
+		return -1;
+	else if (a->re.address > b->re.address)
+		return 1;
+	else if (a->re.size < b->re.size)
+		return -1;
+	else if (a->re.size > b->re.size)
+		return 1;
+	else
+		return 0;
+}
+
+static void sort_reserve_entries(struct boot_info *bi)
+{
+	struct reserve_info *ri, **tbl;
+	int n = 0, i = 0;
+
+	for (ri = bi->reservelist;
+	     ri;
+	     ri = ri->next)
+		n++;
+
+	if (n == 0)
+		return;
+
+	tbl = xmalloc(n * sizeof(*tbl));
+
+	for (ri = bi->reservelist;
+	     ri;
+	     ri = ri->next)
+		tbl[i++] = ri;
+
+	qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
+
+	bi->reservelist = tbl[0];
+	for (i = 0; i < (n-1); i++)
+		tbl[i]->next = tbl[i+1];
+	tbl[n-1]->next = NULL;
+
+	free(tbl);
+}
+
+static int cmp_prop(const void *ax, const void *bx)
+{
+	const struct property *a, *b;
+
+	a = *((const struct property * const *)ax);
+	b = *((const struct property * const *)bx);
+
+	return strcmp(a->name, b->name);
+}
+
+static void sort_properties(struct node *node)
+{
+	int n = 0, i = 0;
+	struct property *prop, **tbl;
+
+	for_each_property(node, prop)
+		n++;
+
+	if (n == 0)
+		return;
+
+	tbl = xmalloc(n * sizeof(*tbl));
+
+	for_each_property(node, prop)
+		tbl[i++] = prop;
+
+	qsort(tbl, n, sizeof(*tbl), cmp_prop);
+
+	node->proplist = tbl[0];
+	for (i = 0; i < (n-1); i++)
+		tbl[i]->next = tbl[i+1];
+	tbl[n-1]->next = NULL;
+
+	free(tbl);
+}
+
+static int cmp_subnode(const void *ax, const void *bx)
+{
+	const struct node *a, *b;
+
+	a = *((const struct node * const *)ax);
+	b = *((const struct node * const *)bx);
+
+	return strcmp(a->name, b->name);
+}
+
+static void sort_subnodes(struct node *node)
+{
+	int n = 0, i = 0;
+	struct node *subnode, **tbl;
+
+	for_each_child(node, subnode)
+		n++;
+
+	if (n == 0)
+		return;
+
+	tbl = xmalloc(n * sizeof(*tbl));
+
+	for_each_child(node, subnode)
+		tbl[i++] = subnode;
+
+	qsort(tbl, n, sizeof(*tbl), cmp_subnode);
+
+	node->children = tbl[0];
+	for (i = 0; i < (n-1); i++)
+		tbl[i]->next_sibling = tbl[i+1];
+	tbl[n-1]->next_sibling = NULL;
+
+	free(tbl);
+}
+
+static void sort_node(struct node *node)
+{
+	struct node *c;
+
+	sort_properties(node);
+	sort_subnodes(node);
+	for_each_child(node, c)
+		sort_node(c);
+}
+
+void sort_tree(struct boot_info *bi)
+{
+	sort_reserve_entries(bi);
+	sort_node(bi->dt);
+}
diff --git a/util_lib/dtc/srcpos.c b/util_lib/dtc/srcpos.c
new file mode 100644
index 0000000..36a38e9
--- /dev/null
+++ b/util_lib/dtc/srcpos.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+
+#include "dtc.h"
+#include "srcpos.h"
+
+
+static char *dirname(const char *path)
+{
+	const char *slash = strrchr(path, '/');
+
+	if (slash) {
+		int len = slash - path;
+		char *dir = xmalloc(len + 1);
+
+		memcpy(dir, path, len);
+		dir[len] = '\0';
+		return dir;
+	}
+	return NULL;
+}
+
+FILE *depfile; /* = NULL */
+struct srcfile_state *current_srcfile; /* = NULL */
+
+/* Detect infinite include recursion. */
+#define MAX_SRCFILE_DEPTH     (100)
+static int srcfile_depth; /* = 0 */
+
+FILE *srcfile_relative_open(const char *fname, char **fullnamep)
+{
+	FILE *f;
+	char *fullname;
+
+	if (streq(fname, "-")) {
+		f = stdin;
+		fullname = xstrdup("<stdin>");
+	} else {
+		if (!current_srcfile || !current_srcfile->dir
+		    || (fname[0] == '/'))
+			fullname = xstrdup(fname);
+		else
+			fullname = join_path(current_srcfile->dir, fname);
+
+		f = fopen(fullname, "r");
+		if (!f)
+			die("Couldn't open \"%s\": %s\n", fname,
+			    strerror(errno));
+	}
+
+	if (depfile)
+		fprintf(depfile, " %s", fullname);
+
+	if (fullnamep)
+		*fullnamep = fullname;
+	else
+		free(fullname);
+
+	return f;
+}
+
+void srcfile_push(const char *fname)
+{
+	struct srcfile_state *srcfile;
+
+	if (srcfile_depth++ >= MAX_SRCFILE_DEPTH)
+		die("Includes nested too deeply");
+
+	srcfile = xmalloc(sizeof(*srcfile));
+
+	srcfile->f = srcfile_relative_open(fname, &srcfile->name);
+	srcfile->dir = dirname(srcfile->name);
+	srcfile->prev = current_srcfile;
+
+	srcfile->lineno = 1;
+	srcfile->colno = 1;
+
+	current_srcfile = srcfile;
+}
+
+int srcfile_pop(void)
+{
+	struct srcfile_state *srcfile = current_srcfile;
+
+	assert(srcfile);
+
+	current_srcfile = srcfile->prev;
+
+	if (fclose(srcfile->f))
+		die("Error closing \"%s\": %s\n", srcfile->name,
+		    strerror(errno));
+
+	/* FIXME: We allow the srcfile_state structure to leak,
+	 * because it could still be referenced from a location
+	 * variable being carried through the parser somewhere.  To
+	 * fix this we could either allocate all the files from a
+	 * table, or use a pool allocator. */
+
+	return current_srcfile ? 1 : 0;
+}
+
+/*
+ * The empty source position.
+ */
+
+struct srcpos srcpos_empty = {
+	.first_line = 0,
+	.first_column = 0,
+	.last_line = 0,
+	.last_column = 0,
+	.file = NULL,
+};
+
+#define TAB_SIZE      8
+
+void srcpos_update(struct srcpos *pos, const char *text, int len)
+{
+	int i;
+
+	pos->file = current_srcfile;
+
+	pos->first_line = current_srcfile->lineno;
+	pos->first_column = current_srcfile->colno;
+
+	for (i = 0; i < len; i++)
+		if (text[i] == '\n') {
+			current_srcfile->lineno++;
+			current_srcfile->colno = 1;
+		} else if (text[i] == '\t') {
+			current_srcfile->colno =
+				ALIGN(current_srcfile->colno, TAB_SIZE);
+		} else {
+			current_srcfile->colno++;
+		}
+
+	pos->last_line = current_srcfile->lineno;
+	pos->last_column = current_srcfile->colno;
+}
+
+struct srcpos *
+srcpos_copy(struct srcpos *pos)
+{
+	struct srcpos *pos_new;
+
+	pos_new = xmalloc(sizeof(struct srcpos));
+	memcpy(pos_new, pos, sizeof(struct srcpos));
+
+	return pos_new;
+}
+
+
+
+void
+srcpos_dump(struct srcpos *pos)
+{
+	printf("file        : \"%s\"\n",
+	       pos->file ? (char *) pos->file : "<no file>");
+	printf("first_line  : %d\n", pos->first_line);
+	printf("first_column: %d\n", pos->first_column);
+	printf("last_line   : %d\n", pos->last_line);
+	printf("last_column : %d\n", pos->last_column);
+	printf("file        : %s\n", pos->file->name);
+}
+
+
+char *
+srcpos_string(struct srcpos *pos)
+{
+	const char *fname = "<no-file>";
+	char *pos_str;
+	int rc;
+
+	if (pos)
+		fname = pos->file->name;
+
+
+	if (pos->first_line != pos->last_line)
+		rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
+			      pos->first_line, pos->first_column,
+			      pos->last_line, pos->last_column);
+	else if (pos->first_column != pos->last_column)
+		rc = asprintf(&pos_str, "%s:%d.%d-%d", fname,
+			      pos->first_line, pos->first_column,
+			      pos->last_column);
+	else
+		rc = asprintf(&pos_str, "%s:%d.%d", fname,
+			      pos->first_line, pos->first_column);
+
+	if (rc == -1)
+		die("Couldn't allocate in srcpos string");
+
+	return pos_str;
+}
+
+void
+srcpos_verror(struct srcpos *pos, char const *fmt, va_list va)
+{
+       const char *srcstr;
+
+       srcstr = srcpos_string(pos);
+
+       fprintf(stdout, "Error: %s ", srcstr);
+       vfprintf(stdout, fmt, va);
+       fprintf(stdout, "\n");
+}
+
+void
+srcpos_error(struct srcpos *pos, char const *fmt, ...)
+{
+	va_list va;
+
+	va_start(va, fmt);
+	srcpos_verror(pos, fmt, va);
+	va_end(va);
+}
+
+
+void
+srcpos_warn(struct srcpos *pos, char const *fmt, ...)
+{
+	const char *srcstr;
+	va_list va;
+	va_start(va, fmt);
+
+	srcstr = srcpos_string(pos);
+
+	fprintf(stderr, "Warning: %s ", srcstr);
+	vfprintf(stderr, fmt, va);
+	fprintf(stderr, "\n");
+
+	va_end(va);
+}
diff --git a/util_lib/dtc/srcpos.h b/util_lib/dtc/srcpos.h
new file mode 100644
index 0000000..ce980ca
--- /dev/null
+++ b/util_lib/dtc/srcpos.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#ifndef _SRCPOS_H_
+#define _SRCPOS_H_
+
+#include <stdio.h>
+
+struct srcfile_state {
+	FILE *f;
+	char *name;
+	char *dir;
+	int lineno, colno;
+	struct srcfile_state *prev;
+};
+
+extern FILE *depfile; /* = NULL */
+extern struct srcfile_state *current_srcfile; /* = NULL */
+
+FILE *srcfile_relative_open(const char *fname, char **fullnamep);
+void srcfile_push(const char *fname);
+int srcfile_pop(void);
+
+struct srcpos {
+    int first_line;
+    int first_column;
+    int last_line;
+    int last_column;
+    struct srcfile_state *file;
+};
+
+#define YYLTYPE struct srcpos
+
+#define YYLLOC_DEFAULT(Current, Rhs, N)						\
+	do {									\
+		if (N) {							\
+			(Current).first_line = YYRHSLOC(Rhs, 1).first_line;	\
+			(Current).first_column = YYRHSLOC(Rhs, 1).first_column;	\
+			(Current).last_line = YYRHSLOC(Rhs, N).last_line;	\
+			(Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
+			(Current).file = YYRHSLOC(Rhs, N).file;			\
+		} else {							\
+			(Current).first_line = (Current).last_line =		\
+				YYRHSLOC(Rhs, 0).last_line;			\
+			(Current).first_column = (Current).last_column =	\
+				YYRHSLOC(Rhs, 0).last_column;			\
+			(Current).file = YYRHSLOC (Rhs, 0).file;		\
+		}								\
+	} while (0)
+
+
+/*
+ * Fictional source position used for IR nodes that are
+ * created without otherwise knowing a true source position.
+ * For example,constant definitions from the command line.
+ */
+extern struct srcpos srcpos_empty;
+
+extern void srcpos_update(struct srcpos *pos, const char *text, int len);
+extern struct srcpos *srcpos_copy(struct srcpos *pos);
+extern char *srcpos_string(struct srcpos *pos);
+extern void srcpos_dump(struct srcpos *pos);
+
+extern void srcpos_verror(struct srcpos *pos, char const *, va_list va)
+     __attribute__((format(printf, 2, 0)));
+extern void srcpos_error(struct srcpos *pos, char const *, ...)
+     __attribute__((format(printf, 2, 3)));
+extern void srcpos_warn(struct srcpos *pos, char const *, ...)
+     __attribute__((format(printf, 2, 3)));
+
+#endif /* _SRCPOS_H_ */
diff --git a/util_lib/dtc/util.c b/util_lib/dtc/util.c
new file mode 100644
index 0000000..d7ac27d
--- /dev/null
+++ b/util_lib/dtc/util.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "util.h"
+
+char *xstrdup(const char *s)
+{
+	int len = strlen(s) + 1;
+	char *dup = xmalloc(len);
+
+	memcpy(dup, s, len);
+
+	return dup;
+}
+
+char *join_path(const char *path, const char *name)
+{
+	int lenp = strlen(path);
+	int lenn = strlen(name);
+	int len;
+	int needslash = 1;
+	char *str;
+
+	len = lenp + lenn + 2;
+	if ((lenp > 0) && (path[lenp-1] == '/')) {
+		needslash = 0;
+		len--;
+	}
+
+	str = xmalloc(len);
+	memcpy(str, path, lenp);
+	if (needslash) {
+		str[lenp] = '/';
+		lenp++;
+	}
+	memcpy(str+lenp, name, lenn+1);
+	return str;
+}
diff --git a/util_lib/dtc/util.h b/util_lib/dtc/util.h
new file mode 100644
index 0000000..9cead84
--- /dev/null
+++ b/util_lib/dtc/util.h
@@ -0,0 +1,56 @@
+#ifndef _UTIL_H
+#define _UTIL_H
+
+/*
+ * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ *                                                                   USA
+ */
+
+static inline void __attribute__((noreturn)) die(char * str, ...)
+{
+	va_list ap;
+
+	va_start(ap, str);
+	fprintf(stderr, "FATAL ERROR: ");
+	vfprintf(stderr, str, ap);
+	exit(1);
+}
+
+static inline void *xmalloc(size_t len)
+{
+	void *new = malloc(len);
+
+	if (!new)
+		die("malloc() failed\n");
+
+	return new;
+}
+
+static inline void *xrealloc(void *p, size_t len)
+{
+	void *new = realloc(p, len);
+
+	if (!new)
+		die("realloc() failed (len=%d)\n", len);
+
+	return new;
+}
+
+extern char *xstrdup(const char *s);
+extern char *join_path(const char *path, const char *name);
+
+#endif /* _UTIL_H */
diff --git a/util_lib/dtc/version_gen.h b/util_lib/dtc/version_gen.h
new file mode 100644
index 0000000..6158b86
--- /dev/null
+++ b/util_lib/dtc/version_gen.h
@@ -0,0 +1 @@
+#define DTC_VERSION "DTC 1.2.0-g37c0b6a0"
-- 
1.7.12



From vgoyal at redhat.com  Wed Sep  5 09:18:52 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Wed, 5 Sep 2012 09:18:52 -0400
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
Message-ID: <20120905131852.GB19749@redhat.com>

On Wed, Sep 05, 2012 at 01:44:45PM +0800, Dave Young wrote:
> 
> In case efi booting, kdump need kernel parameter noefi and acpi_rsdp=
> to disable efi reinit and retrieve the acpi root table physical address.
> 
> Add a function cmdline_add_efi to get the address from /sys/firmware/efi/systab
> If there's no such file or read fail the function will just do nothing.
> 
> Tested efi boot Fedora 17 on thinkpad T420.
> 
> Signed-off-by: Dave Young <dyoung at redhat.com>
> ---
>  kexec/arch/i386/crashdump-x86.c |   47 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 47 insertions(+)
> 
> --- kexec-tools.orig/kexec/arch/i386/crashdump-x86.c
> +++ kexec-tools/kexec/arch/i386/crashdump-x86.c
> @@ -27,6 +27,7 @@
>  #include <sys/types.h>
>  #include <sys/stat.h>
>  #include <unistd.h>
> +#include <fcntl.h>
>  #include "../../kexec.h"
>  #include "../../kexec-elf.h"
>  #include "../../kexec-syscall.h"
> @@ -658,6 +659,51 @@ static int cmdline_add_memmap_acpi(char 
>  	return 0;
>  }
>  
> +/* Appends 'noefi acpi_rsdp=' commandline for efi boot crash dump */
> +static void cmdline_add_efi(char *cmdline)
> +{

Hi Dave,

It might be better to break it down in two functions. One for each
command line parameter.

Also, what's the corelation of efi and acpi_rsdp. Is acpi_rsdp required
only on EFI boot or in general it is required? If it is required in 
general, why kdump works currently.

Thanks
Vivek


From matthew.leach at arm.com  Wed Sep  5 10:34:09 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Wed, 5 Sep 2012 15:34:09 +0100
Subject: [RFC PATCH 0/4]  Add device-tree support to kexec-tools for ARM
In-Reply-To: <20120905123850.GA11453@verge.net.au>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
 <20120905123850.GA11453@verge.net.au>
Message-ID: <000001cd8b73$82e6b4f0$88b41ed0$@leach@arm.com>

Hi Simon,

> Hi Matt,
> 
> are you aware that I posted patches to add ARM DT support
> to kexec-tools a few weeks ago?

Ah, I missed that...
 
> I'm not particularly concerned which version goes in,
> but perhaps we can learn from each others efforts.

After looking over your patches I propose that I incorporate your
generic fs2dt code instead of pulling in the dtc. Also, I use a
different segment for the dtb rather than appending it to the
zImage; I think this approach would be better as it is less
restrictive, however a kernel patch is required to set r2 to the
appropriate address on entry to the new kernel. What are your
thoughts?

If you are happy with this I will submit a v2 set of patches.

Matt




From khalid.aziz at hp.com  Wed Sep  5 19:09:29 2012
From: khalid.aziz at hp.com (Khalid Aziz)
Date: Wed, 05 Sep 2012 17:09:29 -0600
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
Message-ID: <5047DBA9.8030000@hp.com>

On 09/04/2012 11:44 PM, Dave Young wrote:
> In case efi booting, kdump need kernel parameter noefi and acpi_rsdp=
> to disable efi reinit and retrieve the acpi root table physical address.
>
> Add a function cmdline_add_efi to get the address from /sys/firmware/efi/systab
> If there's no such file or read fail the function will just do nothing.
>
> Tested efi boot Fedora 17 on thinkpad T420.
>
> Signed-off-by: Dave Young <dyoung at redhat.com>
> ---
>   kexec/arch/i386/crashdump-x86.c |   47 ++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 47 insertions(+)
>
> --- kexec-tools.orig/kexec/arch/i386/crashdump-x86.c
> +++ kexec-tools/kexec/arch/i386/crashdump-x86.c
> @@ -27,6 +27,7 @@
>   #include <sys/types.h>
>   #include <sys/stat.h>
>   #include <unistd.h>
> +#include <fcntl.h>
>   #include "../../kexec.h"
>   #include "../../kexec-elf.h"
>   #include "../../kexec-syscall.h"
> @@ -658,6 +659,51 @@ static int cmdline_add_memmap_acpi(char
>   	return 0;
>   }
>   
> +/* Appends 'noefi acpi_rsdp=' commandline for efi boot crash dump */
> +static void cmdline_add_efi(char *cmdline)
> +{
> +	int cmdlen, len, fd, ret, i = 0;
> +	char str_efi[64], str_tmp[32];
> +
> +	memset(str_efi, 0x0, sizeof(str_efi));
> +	memset(str_tmp, 0x0, sizeof(str_tmp));
> +	snprintf(str_efi, 18, "%s", " noefi acpi_rsdp=");
> +
> +	fd = open("/sys/firmware/efi/systab", O_RDONLY);
> +	if (fd < 0)
> +		return;
> +
> +	while(1) {
> +		ret = read(fd, &str_tmp[i], 1);
> +		if (ret <= 0)
> +			goto out_close;
> +		if (str_tmp[i] == '\n') {
> +			str_tmp[i] = '\0';
> +			break;
> +		}
> +		i++;
> +	}
> +
> +	if (!(strncmp(str_tmp, "ACPI20=", 7)))
> +		strcat(str_efi, &str_tmp[7]);
> +	else if (!(strncmp(str_tmp, "ACPI=", 5)))
> +		strcat(str_efi, &str_tmp[5]);
> +	else
> +		goto out_close;

This will evaluate only the first line in systab. I do not believe you 
are guaranteed to see ACPI20= or ACPI= in the first line. Here is the 
systab file from my machine:

MPS=0xf4cf0
ACPI20=0xcac3e000
ACPI=0xcac3e000
SMBIOS=0xcac4cf98

We need to parse all the lines in systab.
> +
> +	len = strlen(str_efi);
> +	cmdlen = strlen(cmdline) + len;
> +	if (cmdlen > (COMMAND_LINE_SIZE - 1))
> +		die("Command line overflow\n");
> +	strcat(cmdline, str_efi);
> +
> +	dbgprintf("Command line after adding efi\n");
> +	dbgprintf("%s\n", cmdline);
> +
> +out_close:
> +	close(fd);
> +}
> +
>   static void get_backup_area(unsigned long *start, unsigned long *end)
>   {
>   	const char *iomem = proc_iomem();
> @@ -830,6 +876,7 @@ int load_crashdump_segments(struct kexec
>   	if (delete_memmap(memmap_p, elfcorehdr, memsz) < 0)
>   		return -1;
>   	cmdline_add_memmap(mod_cmdline, memmap_p);
> +	cmdline_add_efi(mod_cmdline);
>   	cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
>   
>   	/* Inform second kernel about the presence of ACPI tables. */
>
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec

I think running a kexec/kdump kernel with "noefi" is not a good idea. 
Today kernel makes very little use of UEFI run time services but this 
might change shortly. I have already seen ideas being proposed to use 
UEFI variables to store kernel panic information which would require 
accessing UEFI runtime services. If the kdump kernel runs into a panic, 
it would be good to be able to use UEFI variables to store some sort of 
tombstone. We might also start using UEFI runtime clock services one of 
these days especially now that all PCs soon will have UEFI due to 
Windows 8 requirements. There might be other ways to deal with EFI 
virtualization issue. I have solved it on a custom ia64 kernel by 
passing the kexec'd kernel a "kexec_reboot" on command line, although I 
wouldn't recommend that approach as a general approach. Creating a new 
kernel command line parameter just to tell the kernel to not virtualize 
EFI sounds excessive. May be we can come up with a different way to tell 
a kexec/kdump kernel to not virtualize EFI, like create a new signature, 
for example "EL32_KEXEC" and "EL64_KEXEC", for 
boot_params.efi_info.efi_loader_signature which tells the kexec/kdump 
kernel to enable EFI but skip the step of virtualizing it. More work 
will be needed to make this work, for example pass the EFI runtime 
service memory map from one kernel to the next so we keep it mapped in 
exact same spot, and other similar mapping issues.

-- 
Khalid


From dyoung at redhat.com  Wed Sep  5 22:48:29 2012
From: dyoung at redhat.com (Dave Young)
Date: Thu, 06 Sep 2012 10:48:29 +0800
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <20120905074550.GA11575@verge.net.au>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <20120905074550.GA11575@verge.net.au>
Message-ID: <50480EFD.5000100@redhat.com>

On 09/05/2012 03:45 PM, Simon Horman wrote:

> On Wed, Sep 05, 2012 at 01:44:45PM +0800, Dave Young wrote:
>>
>> In case efi booting, kdump need kernel parameter noefi and acpi_rsdp=
>> to disable efi reinit and retrieve the acpi root table physical address.
>>
>> Add a function cmdline_add_efi to get the address from /sys/firmware/efi/systab
>> If there's no such file or read fail the function will just do nothing.
>>
>> Tested efi boot Fedora 17 on thinkpad T420.
> 
> Hi Dave,
> 
> conceptually I am fine with this patch.
> However, I do have a few nits in relation to the string handling
> as explained below.


Thanks for review.

> 
>>
>> Signed-off-by: Dave Young <dyoung at redhat.com>
>> ---
>>  kexec/arch/i386/crashdump-x86.c |   47 ++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 47 insertions(+)
>>
>> --- kexec-tools.orig/kexec/arch/i386/crashdump-x86.c
>> +++ kexec-tools/kexec/arch/i386/crashdump-x86.c
>> @@ -27,6 +27,7 @@
>>  #include <sys/types.h>
>>  #include <sys/stat.h>
>>  #include <unistd.h>
>> +#include <fcntl.h>
>>  #include "../../kexec.h"
>>  #include "../../kexec-elf.h"
>>  #include "../../kexec-syscall.h"
>> @@ -658,6 +659,51 @@ static int cmdline_add_memmap_acpi(char 
>>  	return 0;
>>  }
>>  
>> +/* Appends 'noefi acpi_rsdp=' commandline for efi boot crash dump */
>> +static void cmdline_add_efi(char *cmdline)
>> +{
>> +	int cmdlen, len, fd, ret, i = 0;
>> +	char str_efi[64], str_tmp[32];
>> +
>> +	memset(str_efi, 0x0, sizeof(str_efi));
>> +	memset(str_tmp, 0x0, sizeof(str_tmp));
>> +	snprintf(str_efi, 18, "%s", " noefi acpi_rsdp=");
> 
> strncpy() might be be easier on the eyes.


Will switch to use strncpy

> 
>> +
>> +	fd = open("/sys/firmware/efi/systab", O_RDONLY);
>> +	if (fd < 0)
>> +		return;
>> +
>> +	while(1) {
>> +		ret = read(fd, &str_tmp[i], 1);
>> +		if (ret <= 0)
>> +			goto out_close;
>> +		if (str_tmp[i] == '\n') {
>> +			str_tmp[i] = '\0';
>> +			break;
>> +		}
>> +		i++;
>> +	}
> 
> It seems to me that the above code may overflow str_tmp.


Oops, will fix

> 
> Also, I wonder if read(fd, str_tmp, sizeof str_tmp) might make
> things a bit easier over all.


This is fine to me as well. Just also need to end with '\n'

As Khalid said in another reply, the ACPI20= might not be the first
line. will resolve that issue as well.

> 
> Finally, I have a personal preference for "a + i" over "&a[i]".
> Though I'm not going to get excited about it.


Both are fine to me, will convert.

> 
>> +
>> +	if (!(strncmp(str_tmp, "ACPI20=", 7)))
>> +		strcat(str_efi, &str_tmp[7]);
>> +	else if (!(strncmp(str_tmp, "ACPI=", 5)))
>> +		strcat(str_efi, &str_tmp[5]);
>> +	else
>> +		goto out_close;
> 
> I wonder if strncat() would be better above, though I don't think
> an overflow can actually occur if str_tmp is null-terminated.


Will do

> 
>> +
>> +	len = strlen(str_efi);
>> +	cmdlen = strlen(cmdline) + len;
>> +	if (cmdlen > (COMMAND_LINE_SIZE - 1))
>> +		die("Command line overflow\n");
>> +	strcat(cmdline, str_efi);
>> +
>> +	dbgprintf("Command line after adding efi\n");
>> +	dbgprintf("%s\n", cmdline);
>> +
>> +out_close:
>> +	close(fd);
>> +}
>> +
>>  static void get_backup_area(unsigned long *start, unsigned long *end)
>>  {
>>  	const char *iomem = proc_iomem();
>> @@ -830,6 +876,7 @@ int load_crashdump_segments(struct kexec
>>  	if (delete_memmap(memmap_p, elfcorehdr, memsz) < 0)
>>  		return -1;
>>  	cmdline_add_memmap(mod_cmdline, memmap_p);
>> +	cmdline_add_efi(mod_cmdline);
>>  	cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr);
>>  
>>  	/* Inform second kernel about the presence of ACPI tables. */
>>
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec



-- 
Thanks
Dave


From dyoung at redhat.com  Wed Sep  5 22:58:23 2012
From: dyoung at redhat.com (Dave Young)
Date: Thu, 06 Sep 2012 10:58:23 +0800
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <20120905131852.GB19749@redhat.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <20120905131852.GB19749@redhat.com>
Message-ID: <5048114F.4050108@redhat.com>

On 09/05/2012 09:18 PM, Vivek Goyal wrote:

> On Wed, Sep 05, 2012 at 01:44:45PM +0800, Dave Young wrote:
>>
>> In case efi booting, kdump need kernel parameter noefi and acpi_rsdp=
>> to disable efi reinit and retrieve the acpi root table physical address.
>>
>> Add a function cmdline_add_efi to get the address from /sys/firmware/efi/systab
>> If there's no such file or read fail the function will just do nothing.
>>
>> Tested efi boot Fedora 17 on thinkpad T420.
>>
>> Signed-off-by: Dave Young <dyoung at redhat.com>
>> ---
>>  kexec/arch/i386/crashdump-x86.c |   47 ++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 47 insertions(+)
>>
>> --- kexec-tools.orig/kexec/arch/i386/crashdump-x86.c
>> +++ kexec-tools/kexec/arch/i386/crashdump-x86.c
>> @@ -27,6 +27,7 @@
>>  #include <sys/types.h>
>>  #include <sys/stat.h>
>>  #include <unistd.h>
>> +#include <fcntl.h>
>>  #include "../../kexec.h"
>>  #include "../../kexec-elf.h"
>>  #include "../../kexec-syscall.h"
>> @@ -658,6 +659,51 @@ static int cmdline_add_memmap_acpi(char 
>>  	return 0;
>>  }
>>  
>> +/* Appends 'noefi acpi_rsdp=' commandline for efi boot crash dump */
>> +static void cmdline_add_efi(char *cmdline)
>> +{
> 
> Hi Dave,
> 
> It might be better to break it down in two functions. One for each
> command line parameter.


Ok, will do

> 
> Also, what's the corelation of efi and acpi_rsdp. Is acpi_rsdp required
> only on EFI boot or in general it is required? If it is required in 
> general, why kdump works currently.


Hi, here is the background of this issue:
http://lists.infradead.org/pipermail/kexec/2010-March/003889.html

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



-- 
Thanks
Dave


From dyoung at redhat.com  Wed Sep  5 23:18:03 2012
From: dyoung at redhat.com (Dave Young)
Date: Thu, 06 Sep 2012 11:18:03 +0800
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <5047DBA9.8030000@hp.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <5047DBA9.8030000@hp.com>
Message-ID: <504815EB.9000701@redhat.com>

On 09/06/2012 07:09 AM, Khalid Aziz wrote:

> This will evaluate only the first line in systab. I do not believe you
> are guaranteed to see ACPI20= or ACPI= in the first line. Here is the
> systab file from my machine:
> 
> MPS=0xf4cf0
> ACPI20=0xcac3e000
> ACPI=0xcac3e000
> SMBIOS=0xcac4cf98
> 
> We need to parse all the lines in systab.


Thanks for the reporting, will address this in the update patch

> I think running a kexec/kdump kernel with "noefi" is not a good idea.
> Today kernel makes very little use of UEFI run time services but this
> might change shortly. I have already seen ideas being proposed to use
> UEFI variables to store kernel panic information which would require
> accessing UEFI runtime services. If the kdump kernel runs into a panic,
> it would be good to be able to use UEFI variables to store some sort of
> tombstone. We might also start using UEFI runtime clock services one of
> these days especially now that all PCs soon will have UEFI due to
> Windows 8 requirements. There might be other ways to deal with EFI
> virtualization issue. I have solved it on a custom ia64 kernel by
> passing the kexec'd kernel a "kexec_reboot" on command line, although I
> wouldn't recommend that approach as a general approach. Creating a new
> kernel command line parameter just to tell the kernel to not virtualize
> EFI sounds excessive. May be we can come up with a different way to tell
> a kexec/kdump kernel to not virtualize EFI, like create a new signature,
> for example "EL32_KEXEC" and "EL64_KEXEC", for
> boot_params.efi_info.efi_loader_signature which tells the kexec/kdump
> kernel to enable EFI but skip the step of virtualizing it. More work
> will be needed to make this work, for example pass the EFI runtime
> service memory map from one kernel to the next so we keep it mapped in
> exact same spot, and other similar mapping issues.
> 


I'm not so familiar with uefi detail, is the virtualization issue mean
"virtual mode" of efi?  From my understanding for kdump kernel I would
vote for not interacting with bios at all. We have use "noefi" for long
time by passing it to 2nd kernel while kexecing. I prefer to do this way
until we have to switch to other approach.

-- 
Thanks
Dave


From horms at verge.net.au  Wed Sep  5 23:29:02 2012
From: horms at verge.net.au (Simon Horman)
Date: Thu, 6 Sep 2012 12:29:02 +0900
Subject: [RFC PATCH 0/4]  Add device-tree support to kexec-tools for ARM
In-Reply-To: <000001cd8b73$82e6b4f0$88b41ed0$@leach@arm.com>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
 <20120905123850.GA11453@verge.net.au>
 <000001cd8b73$82e6b4f0$88b41ed0$@leach@arm.com>
Message-ID: <20120906032901.GG6432@verge.net.au>

Hi Matt,

On Wed, Sep 05, 2012 at 03:34:09PM +0100, Matthew Leach wrote:
> Hi Simon,
> 
> > Hi Matt,
> > 
> > are you aware that I posted patches to add ARM DT support
> > to kexec-tools a few weeks ago?
> 
> Ah, I missed that...
>  
> > I'm not particularly concerned which version goes in,
> > but perhaps we can learn from each others efforts.
> 
> After looking over your patches I propose that I incorporate your
> generic fs2dt code instead of pulling in the dtc.

Thanks. It was that part of the code that I spent the bulk of my time on.
And although it is still has a few rough edges I would be happy for it
to be used.

> Also, I use a
> different segment for the dtb rather than appending it to the
> zImage; I think this approach would be better as it is less
> restrictive, however a kernel patch is required to set r2 to the
> appropriate address on entry to the new kernel. What are your
> thoughts?

I would prefer to avoid requiring kernel changes unless necessary -
the kernels some of the boards I work with require DT since 3.5.
However, I am happy to discuss this further, there certainly is
merit to a clean implementation.

> If you are happy with this I will submit a v2 set of patches.


From kumagai-atsushi at mxc.nes.nec.co.jp  Thu Sep  6 02:01:36 2012
From: kumagai-atsushi at mxc.nes.nec.co.jp (Atsushi Kumagai)
Date: Thu, 6 Sep 2012 15:01:36 +0900
Subject: makedumpfile-1.5.0: Introduce cyclic mode to fix memory usage.
Message-ID: <20120906150136.e3127181293d85f414d32720@mxc.nes.nec.co.jp>

Hello,

makedumpfile version 1.5.0 is released.
Your comments/patches are welcome.

This version introduces the "cyclic mode" as a default running mode.

Before this version, makedumpfile uses the amount of memory depending 
on physical memory size, because it saves the analytical data for whole
memory at a time.

On the other hand, the cyclic mode uses fixed amount of memory regardless of
physical memory size, because this mode analyzes only constant region of
memory per cycle as below:

  [v1.4.7 or before]
    cycle                       1
                  +-----------------     -----+
    vmcore        |                  ...      | 
                  +-----------------     -----+

  [v1.5.0]
    cycle           1   2   3   4    ...    N
                  +-----------------     -----+
    vmcore        |   |   |   |   |  ...  |   | 
                  +-----------------     -----+

And, the number of cycles is represented as:
 
  N = physical memory size / (page size * bit per byte(8) * BUFSIZE_CYCLIC)

BUFSIZE_CYCLIC is the buffer size for analysis, default size is 1 Mbyte.

BTW, in v1.5.0, the cyclic mode may cause some slow down of filtering process
when N is large. 
I'm going to improve this issue with new filtering logic (called mem_map array logic)
in a future version.

At least in v1.5.0, if you feel the cyclic mode is slow, you can try 2 workarounds:

  1. Use old running mode with "--non-cyclic" option.

  2. Decrease the number of cycles by increasing BUFSIZE_CYCLIC with 
     "--cyclic-buffer" option.

Please refer to the manual page for how to use these options.


Notice:

  1. The cyclic mode doesn't support sadump format and refiltering kdump 
     compressed format, because they will be used in the 1st kernel
     and makedumpfile can allocate enough memory.

  2. The cyclic mode doesn't support Xen in this version, 
     but I'll support it in a future version.

  3. This version will show incorrect and many progress indicator in the cyclic mode.
     I'll fix it in a future version, but it doesn't affect main operation.

  4. I enhanced regression test for this version, and I found the issue
     in old elfutils, so please use elfutils-0.142 or later.
     If you use old elfutils, -g option might fail.

Changelog:
o New feature
   Commits related to "cyclic mode"
    - [PATCH v4 1/12] Introduce cyclic mode to keep memory usage constant. (by Atsushi Kumagai) 269b4f8
    - [PATCH v4 2/12] Prepare partial bitmap for cyclic mode. (by Atsushi Kumagai) d3c062e
    - [PATCH v4 3/12] Change the function related to excluding unnecessary pages. (by Atsushi Kumagai) 38bbc6e
    - [PATCH v4 4/12] Add function to update target region. (by Atsushi Kumagai) 7486ed2
    - [PATCH v4 5/12] Add function to get num_dumpable for cyclic mode. (by Atsushi Kumagai) 2ca2ce8
    - [PATCH v4 6/12] Implement the main routine of cyclic mode for kdump-compressed format. (by Atsushi Kumagai) 7819afa
    - [PATCH v4 7/12] Add function to get number of PT_LOAD for cyclic mode. (by Atsushi Kumagai) 1ff67e0
    - [PATCH v4 8/12] Implement the main routine of cyclic mode for ELF format. (by Atsushi Kumagai) 0310e0f
    - [PATCH v4 9/12] Enabling --split option with cyclic mode. (by Atsushi Kumagai) f6367b4
    - [PATCH v4 10/12] Change num_dumped value to global for debug messages. (by Atsushi Kumagai) db99bbe
    - [PATCH v4 11/12] Remove waste calculation to improve performance. (by Atsushi Kumagai) 253ed35
    - [PATCH v4 12/12] Add --cyclic-buffer option to specify buffer size for cyclic mode. (by Atsushi Kumagai) 79bce69

   Other commit
    - [PATCH] Update README for TODO. (by Atsushi Kumagai) 8c1614c
    - [PATCH] Support newer kernels. (by Atsushi Kumagai) f778363
    - [PATCH] Update necessary elfutils version. (by Atsushi Kumagai) ecafa76

o Bugfix
    - [PATCH] Generic search into anonymous members in search_member(). (by Stefan Bader) ecff242


Plan for v1.5.1:
  - Security key filtering enhancement (by Aravinda Prasad)
  - Add snappy compression support (by HATAYAMA Daisuke)
  - Support Xen-4.1 (by Petr Tesarik, Norbert Trapp)
  - Support for x86_64 1G pages (by Petr Tesarik)
  - keep dumpfile pages in a cache (by Petr Tesarik)
  - Add a missing return statement (by Petr Tesarik)

Explanation of makedumpfile:
  To shorten the size of the dumpfile and the time of creating the
  dumpfile, makedumpfile copies only the necessary pages for analysis
  to the dumpfile from /proc/vmcore. You can specify the kind of
  unnecessary pages with dump_level. If you want to shorten the size
  further, enable the compression of the page data.

Download:
  You can download the latest makedumpfile from the following URL.
  Details of the change are written on the git page of the following site.
  https://sourceforge.net/projects/makedumpfile/

Method of installation:
  You can compile the makedumpfile command as follows;
  1. "tar -zxvf makedumpfile-x.y.z.tar.gz"
  2. "cd makedumpfile-x.y.z"
  3. "make; make install"

Usage:
  makedumpfile [-c] [-E] [-d dump_level] [-x vmlinux] dump_mem dump_file

Example:
  If you want to exclude pages filled by zero, cache pages, user pages
  and free pages and to enable compression, please execute the following
  command.

  # makedumpfile -c -d 31 -x vmlinux /proc/vmcore dumpfile


Thanks
Atsushi Kumagai


From will.deacon at arm.com  Thu Sep  6 05:01:28 2012
From: will.deacon at arm.com (Will Deacon)
Date: Thu, 6 Sep 2012 10:01:28 +0100
Subject: [RFC PATCH 0/4]  Add device-tree support to kexec-tools for ARM
In-Reply-To: <20120906032901.GG6432@verge.net.au>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
 <20120905123850.GA11453@verge.net.au>
 <000001cd8b73$82e6b4f0$88b41ed0$@leach@arm.com>
 <20120906032901.GG6432@verge.net.au>
Message-ID: <20120906090128.GA858@mudshark.cambridge.arm.com>

Hi guys,

On Thu, Sep 06, 2012 at 04:29:02AM +0100, Simon Horman wrote:
> On Wed, Sep 05, 2012 at 03:34:09PM +0100, Matthew Leach wrote:
> > Also, I use a
> > different segment for the dtb rather than appending it to the
> > zImage; I think this approach would be better as it is less
> > restrictive, however a kernel patch is required to set r2 to the
> > appropriate address on entry to the new kernel. What are your
> > thoughts?
> 
> I would prefer to avoid requiring kernel changes unless necessary -
> the kernels some of the boards I work with require DT since 3.5.
> However, I am happy to discuss this further, there certainly is
> merit to a clean implementation.

I had a quick look at both the approaches and it looks like Matthew requires
changes to the host kernel (to load the dtb correctly) and Simon requires
changes to the target kernel (to pick up the dtb correctly).

I would personally prefer changing the host, as the target should ideally
have no knowledge about the kexec. Given that kexec has not supported DT on
ARM so far and these patches have no affect on the existing ATAG mechanism,
I don't think there is a problem with making changes to the kernel.

I also wouldn't like to hedge my bets on CONFIG_ARM_APPENDED_DTB staying
around forever -- it's intended as convenience for legacy bootloaders rather
than something that should be used in preference to passing the dtb via r2.

Will


From horms at verge.net.au  Thu Sep  6 05:09:14 2012
From: horms at verge.net.au (Simon Horman)
Date: Thu, 6 Sep 2012 18:09:14 +0900
Subject: [RFC PATCH 0/4]  Add device-tree support to kexec-tools for ARM
In-Reply-To: <20120906090128.GA858@mudshark.cambridge.arm.com>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
 <20120905123850.GA11453@verge.net.au>
 <000001cd8b73$82e6b4f0$88b41ed0$@leach@arm.com>
 <20120906032901.GG6432@verge.net.au>
 <20120906090128.GA858@mudshark.cambridge.arm.com>
Message-ID: <20120906090914.GA8673@verge.net.au>

Hi Will,

On Thu, Sep 06, 2012 at 10:01:28AM +0100, Will Deacon wrote:
> Hi guys,
> 
> On Thu, Sep 06, 2012 at 04:29:02AM +0100, Simon Horman wrote:
> > On Wed, Sep 05, 2012 at 03:34:09PM +0100, Matthew Leach wrote:
> > > Also, I use a
> > > different segment for the dtb rather than appending it to the
> > > zImage; I think this approach would be better as it is less
> > > restrictive, however a kernel patch is required to set r2 to the
> > > appropriate address on entry to the new kernel. What are your
> > > thoughts?
> > 
> > I would prefer to avoid requiring kernel changes unless necessary -
> > the kernels some of the boards I work with require DT since 3.5.
> > However, I am happy to discuss this further, there certainly is
> > merit to a clean implementation.
> 
> I had a quick look at both the approaches and it looks like Matthew requires
> changes to the host kernel (to load the dtb correctly) and Simon requires
> changes to the target kernel (to pick up the dtb correctly).

Could you explain a little why you feel my patch requires a change to
the target kernel?

> I would personally prefer changing the host, as the target should ideally
> have no knowledge about the kexec. Given that kexec has not supported DT on
> ARM so far and these patches have no affect on the existing ATAG mechanism,
> I don't think there is a problem with making changes to the kernel.

Agreed.

> I also wouldn't like to hedge my bets on CONFIG_ARM_APPENDED_DTB staying
> around forever -- it's intended as convenience for legacy bootloaders rather
> than something that should be used in preference to passing the dtb via r2.

Also agreed.


From will.deacon at arm.com  Thu Sep  6 05:14:06 2012
From: will.deacon at arm.com (Will Deacon)
Date: Thu, 6 Sep 2012 10:14:06 +0100
Subject: [RFC PATCH 0/4]  Add device-tree support to kexec-tools for ARM
In-Reply-To: <20120906090914.GA8673@verge.net.au>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
 <20120905123850.GA11453@verge.net.au>
 <000001cd8b73$82e6b4f0$88b41ed0$@leach@arm.com>
 <20120906032901.GG6432@verge.net.au>
 <20120906090128.GA858@mudshark.cambridge.arm.com>
 <20120906090914.GA8673@verge.net.au>
Message-ID: <20120906091406.GC858@mudshark.cambridge.arm.com>

On Thu, Sep 06, 2012 at 10:09:14AM +0100, Simon Horman wrote:
> Hi Will,
> 
> On Thu, Sep 06, 2012 at 10:01:28AM +0100, Will Deacon wrote:
> > Hi guys,
> > 
> > On Thu, Sep 06, 2012 at 04:29:02AM +0100, Simon Horman wrote:
> > > On Wed, Sep 05, 2012 at 03:34:09PM +0100, Matthew Leach wrote:
> > > > Also, I use a
> > > > different segment for the dtb rather than appending it to the
> > > > zImage; I think this approach would be better as it is less
> > > > restrictive, however a kernel patch is required to set r2 to the
> > > > appropriate address on entry to the new kernel. What are your
> > > > thoughts?
> > > 
> > > I would prefer to avoid requiring kernel changes unless necessary -
> > > the kernels some of the boards I work with require DT since 3.5.
> > > However, I am happy to discuss this further, there certainly is
> > > merit to a clean implementation.
> > 
> > I had a quick look at both the approaches and it looks like Matthew requires
> > changes to the host kernel (to load the dtb correctly) and Simon requires
> > changes to the target kernel (to pick up the dtb correctly).
> 
> Could you explain a little why you feel my patch requires a change to
> the target kernel?

Sure, I may be misunderstanding something, so please shout if that's the
case! Anyway, I was under the impression that you required
CONFIG_ARM_APPENDED_DTB to be enabled in the target so that it can pick up
the new DT. If that's not the case, then you'll need to change the host
kernel to fix up r2 (rather than point it at the KEXEC_ARM_ATAGS_OFFSET,
which is too small for a dtb).

What am I missing?

Will


From mahesh at linux.vnet.ibm.com  Thu Sep  6 05:13:55 2012
From: mahesh at linux.vnet.ibm.com (Mahesh J Salgaonkar)
Date: Thu, 06 Sep 2012 14:43:55 +0530
Subject: [PATCH] kexec: Fix the purgatory Makefile to build arch specific
 purgatory code.
Message-ID: <20120906091332.11848.70361.stgit@mars>

From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

The latest commit 5e48916 has removed a line from purgatory/Makefile that was
responsible for building arch specific purgatory code. This causes kexec -p
(loading of panic kernel) to fail. This patch reverts the deleted line.

Verified this fix on x86_64 and ppc64.

Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
---
 purgatory/Makefile |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/purgatory/Makefile b/purgatory/Makefile
index 711799b..ee1679c 100644
--- a/purgatory/Makefile
+++ b/purgatory/Makefile
@@ -27,6 +27,8 @@ include $(srcdir)/purgatory/arch/s390/Makefile
 include $(srcdir)/purgatory/arch/sh/Makefile
 include $(srcdir)/purgatory/arch/x86_64/Makefile
 
+PURGATORY_SRCS+=$($(ARCH)_PURGATORY_SRCS)
+
 PURGATORY_OBJS = $(call objify, $(PURGATORY_SRCS)) purgatory/sha256.o
 PURGATORY_DEPS = $(call depify, $(PURGATORY_OBJS))
 



From viric at viric.name  Thu Sep  6 05:43:36 2012
From: viric at viric.name (=?iso-8859-1?Q?Llu=EDs?= Batlle i Rossell)
Date: Thu, 6 Sep 2012 11:43:36 +0200
Subject: Getting the kexec on panic
Message-ID: <20120906094336.GJ1943@vicerveza.homeunix.net>

Hello,

while I can load immediately a kernel using kexec, when I set it for panic and
crash with sysrq-c, the computer hangs.

I'm using the nvidia X driver; can it be that it stops the panic handling from
working? I don't understand why it would work with normal kexec though, if it
were the case.

Regards,
Llu?s.


From matthew.leach at arm.com  Thu Sep  6 07:04:50 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Thu, 6 Sep 2012 12:04:50 +0100
Subject: [RFC PATCH 0/4]  Add device-tree support to kexec-tools for ARM
In-Reply-To: <20120906032901.GG6432@verge.net.au>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
 <20120905123850.GA11453@verge.net.au>
 <000001cd8b73$82e6b4f0$88b41ed0$@leach@arm.com>
 <20120906032901.GG6432@verge.net.au>
Message-ID: <000101cd8c1f$6f758520$4e608f60$@leach@arm.com>

Hi Simon,

I have been having some issues using kexec with your dtb patches...

> Thanks. It was that part of the code that I spent the bulk of my time
> on.
> And although it is still has a few rough edges I would be happy for it
> to be used.

I have looked at the output from your generic fs2dt and compared
it to the original dts and all looks okay so I'm happy that this
part of your code works fine.

> I would prefer to avoid requiring kernel changes unless necessary -
> the kernels some of the boards I work with require DT since 3.5.
> However, I am happy to discuss this further, there certainly is
> merit to a clean implementation.

I believe that you are loading the dtb at an offset from the base
of 0x1000, this is where the problem lies in that the dtb can be
corrupted by the page tables of the decompressor.

Also, device trees can contain firmware and as such be on the
order of megabytes in size. This could potentially corrupt the
decompressor image depending upon the order that these two blobs
are written to memory.


I suggest that we put the DTB out of the way, perhaps just after
the initrd segment, or at the initrd_offset in the case that
there is no initrd. This would require a kernel change to set the
correct parameter to the relocate_new_kerenel function, but the
change is minimal.

If you are happy with this, I have a set of patches that does the
job.

Matt




From will.deacon at arm.com  Thu Sep  6 07:19:04 2012
From: will.deacon at arm.com (Will Deacon)
Date: Thu, 6 Sep 2012 12:19:04 +0100
Subject: [RFC PATCH 0/4]  Add device-tree support to kexec-tools for ARM
In-Reply-To: <000101cd8c1f$6f758520$4e608f60$@leach@arm.com>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
 <20120905123850.GA11453@verge.net.au>
 <000001cd8b73$82e6b4f0$88b41ed0$@leach@arm.com>
 <20120906032901.GG6432@verge.net.au>
 <000101cd8c1f$6f758520$4e608f60$@leach@arm.com>
Message-ID: <20120906111904.GF858@mudshark.cambridge.arm.com>

On Thu, Sep 06, 2012 at 12:04:50PM +0100, Matthew Leach wrote:
> I believe that you are loading the dtb at an offset from the base
> of 0x1000, this is where the problem lies in that the dtb can be
> corrupted by the page tables of the decompressor.

Aha, so it is still using the KEXEC_ARM_ATAGS_OFFSET stuff. Sorry if I
confused anybody about the DTB-append comments, I guess I was confusing the
segment layout with the final loaded layout.

It's worth pointing out that, with LPAE kernels, the page tables are larger
and sit at offset 0x3000, so this leaves only 8k for the .dtb which is
definitely not enough.

> I suggest that we put the DTB out of the way, perhaps just after
> the initrd segment, or at the initrd_offset in the case that
> there is no initrd. This would require a kernel change to set the
> correct parameter to the relocate_new_kerenel function, but the
> change is minimal.

I'm fine with changing the kernel, as long as it doesn't break existing
users (it doesn't).

Will


From ptesarik at suse.cz  Thu Sep  6 11:50:52 2012
From: ptesarik at suse.cz (Petr Tesarik)
Date: Thu, 6 Sep 2012 17:50:52 +0200
Subject: [PATCH] makedumpfile: keep dumpfile pages in a cache
In-Reply-To: <201209030904.03661.ptesarik@suse.cz>
References: <201208281949.50286.ptesarik@suse.cz>
 <20120903124233.61eafa52ffaed6a38a23710d@mxc.nes.nec.co.jp>
 <201209030904.03661.ptesarik@suse.cz>
Message-ID: <201209061750.52702.ptesarik@suse.cz>

Dne Po 3. z??? 2012 09:04:03 Petr Tesarik napsal(a):
> Dne Po 3. z??? 2012 05:42:33 Atsushi Kumagai napsal(a):
> > Hello Petr,
> > 
> > On Tue, 28 Aug 2012 19:49:49 +0200
> > 
> > Petr Tesarik <ptesarik at suse.cz> wrote:
> > > Add a simple cache for pages read from the dumpfile.
> > > 
> > > This is a big win if we read consecutive data from one page, e.g.
> > > page descriptors, or even page table entries.
> > > 
> > > Note that makedumpfile now always reads a complete page. This was
> > > already the case with kdump-compressed and sadump formats, but
> > > makedumpfile was throwing most of the data away. For the
> > > kdump-compressed case, we may actually save a lot of decompression,
> > > too.
> > > 
> > > I tried to keep the cache small to minimize memory footprint, but it
> > > should be big enough to hold all pages to do 4-level paging plus some
> > > data. This is needed e.g. for vmalloc areas or Xen page frame table
> > > data, which are not contiguous in physical memory.
> > > 
> > > Signed-off-by: Petr Tesarik <ptesarik at suse.cz>
> > 
> > It's interesting to me. I want to know how performance will be improved
> > with this patch, so do you have speed measurements ?
> 
> Not really. I only measured the hit/miss ratio, and with filtering Xen domU
> and dump level 0, I got the following on a small system (2G RAM):
> 
> cache hit: 1818880  cache miss: 1873
> 
> The improvement isn't much for non-Xen case, because the hits are mostly
> due to virtual-to-physical translations, and most of Linux data is stored
> at virtual addresses that can be resolved by adding/subtracting a fixed
> offset.
> 
> Of course, you will also win only the syscall overhead, because Linux keeps
> the data in the kernel pagecache anyway. I'll measure the times for you on
> a reasonably large system (~256G) and send the results here.

I couldn't get a medium-sized system for testing, so I performed some 
measurements on a 64G system. I ran makedumpfile repeatedly from the kdump 
environment. First run was used to cache target filesystem metadata, and the 
cache was not dropped between runs to minimize effects of the target 
filesystem. I ran it against /proc/vmcore, i.e. the input file was always 
resident, nothing to skew the results.

I tried with a kdump file with no compression (to get gzip/LZO out of the 
picture) and an ELF file. For the Xen case I only did the ELF file, because 
kdump is not available.

First I ran it on bare metal. There was a slight improvement for -d31:

kdump no cache:
6.32user 55.20system 1:15.60elapsed 81%CPU (0avgtext+0avgdata 
4800maxresident)k
2080inputs+5714296outputs (2major+342minor)pagefaults 0swaps

kdump with cache:
6.02user 24.58system 0:46.51elapsed 65%CPU (0avgtext+0avgdata 
4912maxresident)k
1864inputs+5714288outputs (2major+350minor)pagefaults 0swaps

ELF no cache:
7.58user 74.25system 1:59.52elapsed 68%CPU (0avgtext+0avgdata 
4800maxresident)k
728inputs+9288824outputs (1major+342minor)pagefaults 0swaps

ELF with cache:
7.43user 44.21system 1:17.41elapsed 66%CPU (0avgtext+0avgdata 
4896maxresident)k
728inputs+9288792outputs (1major+349minor)pagefaults 0swaps

To sum it up, I can see an improvement of approx. 50% in system time. The 
increase in memory consumption is a bit more than I would expect (why do I see 
~100k for a cache of 12k?), but acceptable nevertheless. I can see a slight 
increase in user time (approx. 25%) for the kdump case, which could be 
attributed to the cache overhead. I don't have any explanation for the 
decreased user time for the ELF case, but it's consistent.

I also tried running makedumpfile with -d1. This results in long sequential 
reads, so it's the worst case for a simple LRU-policy cache. The results are 
too unstable to make a reliable measurement, but there seems to be a slight 
performance hit. It is certainly less than 5% total time.

I think there are two reasons for that:

1. We're copying file data twice for each page (once from the kernel page 
cache to the process space, and once from the internal cache to the 
destination).
2. Instead of reusing the same data location, we're rotating 8 different pages 
(or even up to twice as much if the allocated space is neither continuous  nor 
page-aligned). This stresses both for the CPU's L1 d-cache and the TLB a tiny 
bit more. Note that in the /proc/vmcore case, the kernel sequentially maps all 
physical memory of the crashed system, so every cache page may be evicted 
before we get to using it again. This could explain why I observe an increase 
in system time despite making less system calls.

There's a lot of things I could do to regain the old performance, if anybody 
is concerned about the slight performance regression for this worst case. Just 
let me know.

Second, I ran with the Xen hypervisor. Since dump levels greater than 1 don't 
work, I ran with '-E -X -d1'. Even though this includes the inefficient page 
walk described above, the improvement was immense.

no cache:
95.33user 657.18system 13:08.40elapsed 95%CPU (0avgtext+0avgdata 
5440maxresident)k
704inputs+6563856outputs (1major+388minor)pagefaults 0swaps

with cache:
61.14user 110.15system 3:24.24elapsed 83%CPU (0avgtext+0avgdata 
5584maxresident)k
2360inputs+6563872outputs (2major+396minor)pagefaults 0swaps

In short, almost 80% shorter total time.

Petr Tesarik
SUSE Linux


From khalid.aziz at hp.com  Thu Sep  6 13:57:34 2012
From: khalid.aziz at hp.com (Khalid Aziz)
Date: Thu, 06 Sep 2012 11:57:34 -0600
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <504815EB.9000701@redhat.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <5047DBA9.8030000@hp.com> <504815EB.9000701@redhat.com>
Message-ID: <5048E40E.7040003@hp.com>

On 09/05/2012 09:18 PM, Dave Young wrote:
>
>> I think running a kexec/kdump kernel with "noefi" is not a good idea.
>> Today kernel makes very little use of UEFI run time services but this
>> might change shortly. I have already seen ideas being proposed to use
>> UEFI variables to store kernel panic information which would require
>> accessing UEFI runtime services. If the kdump kernel runs into a panic,
>> it would be good to be able to use UEFI variables to store some sort of
>> tombstone. We might also start using UEFI runtime clock services one of
>> these days especially now that all PCs soon will have UEFI due to
>> Windows 8 requirements. There might be other ways to deal with EFI
>> virtualization issue. I have solved it on a custom ia64 kernel by
>> passing the kexec'd kernel a "kexec_reboot" on command line, although I
>> wouldn't recommend that approach as a general approach. Creating a new
>> kernel command line parameter just to tell the kernel to not virtualize
>> EFI sounds excessive. May be we can come up with a different way to tell
>> a kexec/kdump kernel to not virtualize EFI, like create a new signature,
>> for example "EL32_KEXEC" and "EL64_KEXEC", for
>> boot_params.efi_info.efi_loader_signature which tells the kexec/kdump
>> kernel to enable EFI but skip the step of virtualizing it. More work
>> will be needed to make this work, for example pass the EFI runtime
>> service memory map from one kernel to the next so we keep it mapped in
>> exact same spot, and other similar mapping issues.
>>
>
> I'm not so familiar with uefi detail, is the virtualization issue mean
> "virtual mode" of efi?  From my understanding for kdump kernel I would
> vote for not interacting with bios at all. We have use "noefi" for long
> time by passing it to 2nd kernel while kexecing. I prefer to do this way
> until we have to switch to other approach.
>
Yes, that is what I mean by virtualizing issue. Using "noefi" for kdump 
kernel will keep it from using any runtime EFI services. That could mean 
kdump kernel may not be able to read clock or use EFI variables to store 
a tombstone in case it runs into trouble. Is that acceptable?

For the kexec'd kernel (not kdump kernel), being able to use runtime EFI 
services will be essential as we move to EFI machines. We will have to 
support enabling EFI on a kexec'd kernel. Does that sound reasonable?

-- 
Khalid


From daniel.baluta at gmail.com  Thu Sep  6 14:48:43 2012
From: daniel.baluta at gmail.com (Daniel Baluta)
Date: Thu, 6 Sep 2012 21:48:43 +0300
Subject: Getting the kexec on panic
In-Reply-To: <20120906094336.GJ1943@vicerveza.homeunix.net>
References: <20120906094336.GJ1943@vicerveza.homeunix.net>
Message-ID: <CAEnQRZCL--p6jB2H6gN7=sPHCnpQaDpJgu0RuHHDmX89hGhWmw@mail.gmail.com>

On Thu, Sep 6, 2012 at 12:43 PM, Llu?s Batlle i Rossell
<viric at viric.name> wrote:
> Hello,
>
> while I can load immediately a kernel using kexec, when I set it for panic and
> crash with sysrq-c, the computer hangs.
>
> I'm using the nvidia X driver; can it be that it stops the panic handling from
> working? I don't understand why it would work with normal kexec though, if it
> were the case.

Hello,

Did you setup a kernel for load on panic? Can you paste the output for
# cat /proc/cmdline ?

thanks,
Daniel.


From vgoyal at redhat.com  Thu Sep  6 16:24:06 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Thu, 6 Sep 2012 16:24:06 -0400
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <5047DBA9.8030000@hp.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <5047DBA9.8030000@hp.com>
Message-ID: <20120906202406.GD27209@redhat.com>

On Wed, Sep 05, 2012 at 05:09:29PM -0600, Khalid Aziz wrote:
[..]
> More work will be needed to make this work, for example pass the
> EFI runtime service memory map from one kernel to the next so we
> keep it mapped in exact same spot, and other similar mapping issues.

Hi Khalid,

This sounds like significant amount of work. So till this work really
gets merged, noefi is not a bad option. Atleast it will allow us
to capture dump. And once a generic fix is in, one can remove it and
build more fancy features which make use of EFI services in second
kernel?

Thanks
Vivek


From vgoyal at redhat.com  Thu Sep  6 16:46:42 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Thu, 6 Sep 2012 16:46:42 -0400
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <5048114F.4050108@redhat.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <20120905131852.GB19749@redhat.com> <5048114F.4050108@redhat.com>
Message-ID: <20120906204642.GE27209@redhat.com>

On Thu, Sep 06, 2012 at 10:58:23AM +0800, Dave Young wrote:

[..]
> > Also, what's the corelation of efi and acpi_rsdp. Is acpi_rsdp required
> > only on EFI boot or in general it is required? If it is required in 
> > general, why kdump works currently.
> 
> 
> Hi, here is the background of this issue:
> http://lists.infradead.org/pipermail/kexec/2010-March/003889.html

Ok, looks like this is EFI specific. So keeping noefi and acpi_rsdp
together makes sense.

Thanks
Vivek


From horms at verge.net.au  Thu Sep  6 18:00:34 2012
From: horms at verge.net.au (Simon Horman)
Date: Fri, 7 Sep 2012 07:00:34 +0900
Subject: [RFC PATCH 0/4]  Add device-tree support to kexec-tools for ARM
In-Reply-To: <000101cd8c1f$6f758520$4e608f60$@leach@arm.com>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
 <20120905123850.GA11453@verge.net.au>
 <000001cd8b73$82e6b4f0$88b41ed0$@leach@arm.com>
 <20120906032901.GG6432@verge.net.au>
 <000101cd8c1f$6f758520$4e608f60$@leach@arm.com>
Message-ID: <20120906220031.GA10174@verge.net.au>

On Thu, Sep 06, 2012 at 12:04:50PM +0100, Matthew Leach wrote:
> Hi Simon,
> 
> I have been having some issues using kexec with your dtb patches...
> 
> > Thanks. It was that part of the code that I spent the bulk of my time
> > on.
> > And although it is still has a few rough edges I would be happy for it
> > to be used.
> 
> I have looked at the output from your generic fs2dt and compared
> it to the original dts and all looks okay so I'm happy that this
> part of your code works fine.

:)

> > I would prefer to avoid requiring kernel changes unless necessary -
> > the kernels some of the boards I work with require DT since 3.5.
> > However, I am happy to discuss this further, there certainly is
> > merit to a clean implementation.
> 
> I believe that you are loading the dtb at an offset from the base
> of 0x1000, this is where the problem lies in that the dtb can be
> corrupted by the page tables of the decompressor.

Of course, sorry for missing that.

> Also, device trees can contain firmware and as such be on the
> order of megabytes in size. This could potentially corrupt the
> decompressor image depending upon the order that these two blobs
> are written to memory.

Yes, I see that now. The dtb I was using for testing was rather small,
less than 200b IIRC.

Actually, I accidently left debug code in the patchset that prints a hex
dump of the dtb to stdtout. That ought to be removed but that the dump
fited comfortably in few dozen lines illustrates how small a blob I had.

> I suggest that we put the DTB out of the way, perhaps just after
> the initrd segment, or at the initrd_offset in the case that
> there is no initrd. This would require a kernel change to set the
> correct parameter to the relocate_new_kerenel function, but the
> change is minimal.
> 
> If you are happy with this, I have a set of patches that does the
> job.

Thanks, for the explanation, and thanks to Will for his.
I'm happy with the approach that you propose.



From horms at verge.net.au  Thu Sep  6 18:03:29 2012
From: horms at verge.net.au (Simon Horman)
Date: Fri, 7 Sep 2012 07:03:29 +0900
Subject: [RFC PATCH 0/4]  Add device-tree support to kexec-tools for ARM
In-Reply-To: <20120906091406.GC858@mudshark.cambridge.arm.com>
References: <1346845443-32242-1-git-send-email-matthew.leach@arm.com>
 <20120905123850.GA11453@verge.net.au>
 <000001cd8b73$82e6b4f0$88b41ed0$@leach@arm.com>
 <20120906032901.GG6432@verge.net.au>
 <20120906090128.GA858@mudshark.cambridge.arm.com>
 <20120906090914.GA8673@verge.net.au>
 <20120906091406.GC858@mudshark.cambridge.arm.com>
Message-ID: <20120906220329.GB10174@verge.net.au>

On Thu, Sep 06, 2012 at 10:14:06AM +0100, Will Deacon wrote:
> On Thu, Sep 06, 2012 at 10:09:14AM +0100, Simon Horman wrote:
> > Hi Will,
> > 
> > On Thu, Sep 06, 2012 at 10:01:28AM +0100, Will Deacon wrote:
> > > Hi guys,
> > > 
> > > On Thu, Sep 06, 2012 at 04:29:02AM +0100, Simon Horman wrote:
> > > > On Wed, Sep 05, 2012 at 03:34:09PM +0100, Matthew Leach wrote:
> > > > > Also, I use a
> > > > > different segment for the dtb rather than appending it to the
> > > > > zImage; I think this approach would be better as it is less
> > > > > restrictive, however a kernel patch is required to set r2 to the
> > > > > appropriate address on entry to the new kernel. What are your
> > > > > thoughts?
> > > > 
> > > > I would prefer to avoid requiring kernel changes unless necessary -
> > > > the kernels some of the boards I work with require DT since 3.5.
> > > > However, I am happy to discuss this further, there certainly is
> > > > merit to a clean implementation.
> > > 
> > > I had a quick look at both the approaches and it looks like Matthew requires
> > > changes to the host kernel (to load the dtb correctly) and Simon requires
> > > changes to the target kernel (to pick up the dtb correctly).
> > 
> > Could you explain a little why you feel my patch requires a change to
> > the target kernel?
> 
> Sure, I may be misunderstanding something, so please shout if that's the
> case! Anyway, I was under the impression that you required
> CONFIG_ARM_APPENDED_DTB to be enabled in the target so that it can pick up
> the new DT. If that's not the case, then you'll need to change the host
> kernel to fix up r2 (rather than point it at the KEXEC_ARM_ATAGS_OFFSET,
> which is too small for a dtb).

Thanks. It was not my intention that  CONFIG_ARM_APPENDED_DTB is required,
though due to limitations of the bootloader on the board I was using I did
have that option enabled for the host kernel.

Thanks for pointing out the size issue with using KEXEC_ARM_ATAGS_OFFSET,
I had overlooked that.

I think the best way forward, as both you and Matt suggested earlier,
is to modify the host kernel.



From dev at snitselaar.org  Thu Sep  6 18:06:51 2012
From: dev at snitselaar.org (Jerry Snitselaar)
Date: Thu, 6 Sep 2012 15:06:51 -0700
Subject: Getting the kexec on panic
In-Reply-To: <20120906094336.GJ1943@vicerveza.homeunix.net>
References: <20120906094336.GJ1943@vicerveza.homeunix.net>
Message-ID: <20120906220651.GB1745@cantor.Home>

On Thu Sep 06 12, Llu?s Batlle i Rossell wrote:
> Hello,
> 
> while I can load immediately a kernel using kexec, when I set it for panic and
> crash with sysrq-c, the computer hangs.
> 
> I'm using the nvidia X driver; can it be that it stops the panic handling from
> working? I don't understand why it would work with normal kexec though, if it
> were the case.
> 
> Regards,
> Llu?s.

Hi Lluis,


What kernel are you using? The commit 722bc6b "x86/mm: Fix the size calculation of mapping tables" which started showing up in 3.5-rc1 causes problems for the crash kernel. You might try this patchset[1] from Jacob Shin and see if it resolves the problem for you if you are experiencing your problem on a 3.5-rc1+ kernel.

[1] https://lkml.org/lkml/2012/8/24/474

Regards,
Jerry

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


From horms at verge.net.au  Thu Sep  6 18:06:53 2012
From: horms at verge.net.au (Simon Horman)
Date: Fri, 7 Sep 2012 07:06:53 +0900
Subject: [PATCH] kexec: Fix the purgatory Makefile to build arch specific
 purgatory code.
In-Reply-To: <20120906091332.11848.70361.stgit@mars>
References: <20120906091332.11848.70361.stgit@mars>
Message-ID: <20120906220653.GC10174@verge.net.au>

On Thu, Sep 06, 2012 at 02:43:55PM +0530, Mahesh J Salgaonkar wrote:
> From: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
> 
> The latest commit 5e48916 has removed a line from purgatory/Makefile that was
> responsible for building arch specific purgatory code. This causes kexec -p
> (loading of panic kernel) to fail. This patch reverts the deleted line.
> 
> Verified this fix on x86_64 and ppc64.
> 
> Signed-off-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>

Thanks, applied.


From dyoung at redhat.com  Fri Sep  7 04:56:13 2012
From: dyoung at redhat.com (Dave Young)
Date: Fri, 07 Sep 2012 16:56:13 +0800
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <5048E40E.7040003@hp.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <5047DBA9.8030000@hp.com> <504815EB.9000701@redhat.com>
 <5048E40E.7040003@hp.com>
Message-ID: <5049B6AD.9000304@redhat.com>

On 09/07/2012 01:57 AM, Khalid Aziz wrote:

> On 09/05/2012 09:18 PM, Dave Young wrote:
>>
>>> I think running a kexec/kdump kernel with "noefi" is not a good idea.
>>> Today kernel makes very little use of UEFI run time services but this
>>> might change shortly. I have already seen ideas being proposed to use
>>> UEFI variables to store kernel panic information which would require
>>> accessing UEFI runtime services. If the kdump kernel runs into a panic,
>>> it would be good to be able to use UEFI variables to store some sort of
>>> tombstone. We might also start using UEFI runtime clock services one of
>>> these days especially now that all PCs soon will have UEFI due to
>>> Windows 8 requirements. There might be other ways to deal with EFI
>>> virtualization issue. I have solved it on a custom ia64 kernel by
>>> passing the kexec'd kernel a "kexec_reboot" on command line, although I
>>> wouldn't recommend that approach as a general approach. Creating a new
>>> kernel command line parameter just to tell the kernel to not virtualize
>>> EFI sounds excessive. May be we can come up with a different way to tell
>>> a kexec/kdump kernel to not virtualize EFI, like create a new signature,
>>> for example "EL32_KEXEC" and "EL64_KEXEC", for
>>> boot_params.efi_info.efi_loader_signature which tells the kexec/kdump
>>> kernel to enable EFI but skip the step of virtualizing it. More work
>>> will be needed to make this work, for example pass the EFI runtime
>>> service memory map from one kernel to the next so we keep it mapped in
>>> exact same spot, and other similar mapping issues.
>>>
>>
>> I'm not so familiar with uefi detail, is the virtualization issue mean
>> "virtual mode" of efi?  From my understanding for kdump kernel I would
>> vote for not interacting with bios at all. We have use "noefi" for long
>> time by passing it to 2nd kernel while kexecing. I prefer to do this way
>> until we have to switch to other approach.
>>
> Yes, that is what I mean by virtualizing issue. Using "noefi" for kdump
> kernel will keep it from using any runtime EFI services. That could mean
> kdump kernel may not be able to read clock or use EFI variables to store
> a tombstone in case it runs into trouble. Is that acceptable?
> 
> For the kexec'd kernel (not kdump kernel), being able to use runtime EFI
> services will be essential as we move to EFI machines. We will have to
> support enabling EFI on a kexec'd kernel. Does that sound reasonable?
> 


It's probably needed, but currently relevant implementation  is not
ready especially efi init code for kdump. We can address this once it's ok.

I did some digging about the efi boot kdump in slackware with kernel
from latest linus tree. I'm surprise that kdump works even without these
"noefi" and "acpi_rsdp="

With fedora 17 3.4.3 kernel passing "acpi_rsdp=" is enough for kdump
kernel booting.

Actually in x86 setup code if bootloader do not pass correct efi_info in
boot_params efi_enabled will be set to 0 automaticlly.

So as for this patch 'noefi' is not needed.

I will do more testing to see why linus tree works without "acpi_rsdp="


-- 
Thanks
Dave


From matthew.leach at arm.com  Fri Sep  7 05:11:22 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Fri,  7 Sep 2012 10:11:22 +0100
Subject: [PATCH 3/7] fs2dt: Add a generic copy of fs2dt
In-Reply-To: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
References: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
Message-ID: <1347009086-16506-4-git-send-email-matthew.leach@arm.com>

From: Simon Horman <horms at verge.net.au>

The motivation for this is to remove duplicated code by sharing the fs2dt
between different architectures.

The code added by this patch is very
close to the code currently used by ppc64, and thus migrating that
architecture should not be difficult.  The 32bit powerpc code is a little
different and thus more care is needed when migrating that architecture
to this code.

Unfortunately I do not have any powerpc equipment available to test this
code.

Signed-off-by: Simon Horman <horms at verge.net.au>
---
 kexec/Makefile            |   6 +
 kexec/arch_reuse_initrd.c |   2 +
 kexec/fs2dt.c             | 781 ++++++++++++++++++++++++++++++++++++++++++++++
 kexec/fs2dt.h             |  38 +++
 kexec/kexec.h             |   5 +
 5 files changed, 832 insertions(+)
 create mode 100644 kexec/fs2dt.c
 create mode 100644 kexec/fs2dt.h

diff --git a/kexec/Makefile b/kexec/Makefile
index dff8da6..8a6138d 100644
--- a/kexec/Makefile
+++ b/kexec/Makefile
@@ -64,6 +64,10 @@ dist				+= kexec/kexec-uImage.c
 $(ARCH)_UIMAGE			=
 KEXEC_SRCS			+= $($(ARCH)_UIMAGE)
 
+dist				+= kexec/fs2dt.c kexec/fs2dt.h
+$(ARCH)_FS2DT			=
+KEXEC_SRCS			+= $($(ARCH)_FS2DT)
+
 include $(srcdir)/kexec/arch/alpha/Makefile
 include $(srcdir)/kexec/arch/arm/Makefile
 include $(srcdir)/kexec/arch/i386/Makefile
@@ -95,6 +99,8 @@ $(KEXEC): $(KEXEC_OBJS) $(UTIL_LIB)
 
 $(KEXEC): CPPFLAGS+=-I$(srcdir)/kexec/arch/$(ARCH)/include
 
+kexec/fs2dt.o: CPPFLAGS+=$($(ARCH)_FS2DT_INCLUDE)
+
 $(KEXEC_MANPAGE): kexec/kexec.8
 	@$(MKDIR) -p     $(MANDIR)/man8
 	cp $^ $(KEXEC_MANPAGE)
diff --git a/kexec/arch_reuse_initrd.c b/kexec/arch_reuse_initrd.c
index 477a76d..b92b8d8 100644
--- a/kexec/arch_reuse_initrd.c
+++ b/kexec/arch_reuse_initrd.c
@@ -1,5 +1,7 @@
 #include "kexec.h"
 
+unsigned char reuse_initrd = 0;
+
 void arch_reuse_initrd(void)
 {
 	die("--reuseinitrd not implemented on this architecture\n");
diff --git a/kexec/fs2dt.c b/kexec/fs2dt.c
new file mode 100644
index 0000000..1fe0dfb
--- /dev/null
+++ b/kexec/fs2dt.c
@@ -0,0 +1,781 @@
+/*
+ * fs2dt: creates a flattened device-tree
+ *
+ * Copyright (C) 2004,2005  Milton D Miller II, IBM Corporation
+ * Copyright (C) 2005  R Sharada (sharada at in.ibm.com), 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 (version 2 of the License).
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define _GNU_SOURCE
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include "kexec.h"
+#include "fs2dt.h"
+
+#define MAXPATH 1024		/* max path name length */
+#define NAMESPACE 16384		/* max bytes for property names */
+#define INIT_TREE_WORDS 65536	/* Initial num words for prop values */
+#define MEMRESERVE 256		/* max number of reserved memory blocks */
+#define MEM_RANGE_CHUNK_SZ 2048 /* Initial num dwords for mem ranges */
+
+static char pathname[MAXPATH], *pathstart;
+static char propnames[NAMESPACE] = { 0 };
+static unsigned *dt_base, *dt;
+static unsigned int dt_cur_size;
+static unsigned long long mem_rsrv[2*MEMRESERVE] = { 0ULL, 0ULL };
+
+static int crash_param = 0;
+static char local_cmdline[COMMAND_LINE_SIZE] = { "" };
+
+extern unsigned char reuse_initrd;
+
+/* Used for enabling printing message from purgatory code
+ * Only has implemented for PPC64 */
+int my_debug;
+
+/* This provides the behaviour of hte existing ppc64 implementation */
+static void pad_structure_block(size_t len) {
+#ifdef NEED_STRUCTURE_BLOCK_EXTRA_PAD
+	if ((len >= 8) && ((unsigned long)dt & 0x4))
+		dt++;
+#endif
+}
+
+/* Before we add something to the dt, reserve N words using this.
+ * If there isn't enough room, it's realloced -- and you don't overflow and
+ * splat bits of your heap. 
+ */
+static void dt_reserve(unsigned **dt_ptr, unsigned words)
+{
+	unsigned int sz = INIT_TREE_WORDS;
+
+	if (sz < words)
+		sz = words;
+
+	if (((*dt_ptr - dt_base) + words) >= dt_cur_size) {
+		int offset;
+		unsigned int new_size = dt_cur_size + sz;
+		unsigned *new_dt = realloc(dt_base, new_size*4);
+
+		if (!new_dt)
+			die("unrecoverable error: Can't realloc %d bytes for "
+			    "device tree\n", new_size*4);
+		offset = *dt_ptr - dt_base;
+		dt_base = new_dt;
+		dt_cur_size = new_size;
+		*dt_ptr = cpu_to_be32((unsigned)dt_base + offset);
+		memset(*dt_ptr, 0, (new_size - offset)*4);
+	}
+}
+
+void reserve(unsigned long long where, unsigned long long length)
+{
+	size_t offset;
+
+	for (offset = 0; be64_to_cpu(mem_rsrv[offset + 1]); offset += 2)
+		;
+
+	if (offset + 4 >= 2 * MEMRESERVE)
+		die("unrecoverable error: exhasuted reservation meta data\n");
+
+	mem_rsrv[offset] = cpu_to_be64(where);
+	mem_rsrv[offset + 1] = cpu_to_be64(length);
+	mem_rsrv[offset + 2] = mem_rsrv[offset + 3] = cpu_to_be64(0);
+}
+
+/* look for properties we need to reserve memory space for */
+static void checkprop(char *name, unsigned *data, int len)
+{
+	static unsigned long long base, size, end;
+
+	if ((data == NULL) && (base || size || end))
+		die("unrecoverable error: no property data");
+	else if (!strcmp(name, "linux,rtas-base"))
+		base = *data;
+	else if (!strcmp(name, "linux,tce-base"))
+		base = *(unsigned long long *) data;
+	else if (!strcmp(name, "rtas-size") ||
+			!strcmp(name, "linux,tce-size"))
+		size = *data;
+	else if (reuse_initrd && !strcmp(name, "linux,initrd-start"))
+		if (len == 8)
+			base = *(unsigned long long *) data;
+		else
+			base = *data;
+	else if (reuse_initrd && !strcmp(name, "linux,initrd-end"))
+		end = *(unsigned long long *) data;
+
+	if (size && end)
+		die("unrecoverable error: size and end set at same time\n");
+	if (base && size) {
+		reserve(base, size);
+		base = size = 0;
+	}
+	if (base && end) {
+		reserve(base, end-base);
+		base = end = 0;
+	}
+}
+
+/*
+ * return the property index for a property name, creating a new one
+ * if needed.
+ */
+static unsigned propnum(const char *name)
+{
+	unsigned offset = 0;
+
+	while(propnames[offset])
+		if (strcmp(name, propnames+offset))
+			offset += strlen(propnames+offset)+1;
+		else
+			return offset;
+
+	if (NAMESPACE - offset < strlen(name) + 1)
+		die("unrecoverable error: propnames overrun\n");
+
+	strcpy(propnames+offset, name);
+
+	return offset;
+}
+
+#ifdef HAVE_DYNAMIC_MEMORY
+static void add_dyn_reconf_usable_mem_property__(int fd)
+{
+	char fname[MAXPATH], *bname;
+	uint64_t buf[32];
+	uint64_t *ranges;
+	int ranges_size = MEM_RANGE_CHUNK_SZ;
+	uint64_t base, end, loc_base, loc_end;
+	size_t i, rngs_cnt, range;
+	int rlen = 0;
+	int tmp_indx;
+
+	strcpy(fname, pathname);
+	bname = strrchr(fname, '/');
+	bname[0] = '\0';
+	bname = strrchr(fname, '/');
+	if (strncmp(bname, "/ibm,dynamic-reconfiguration-memory", 36))
+		return;
+
+	if (lseek(fd, 4, SEEK_SET) < 0)
+		die("unrecoverable error: error seeking in \"%s\": %s\n",
+			pathname, strerror(errno));
+
+	ranges = malloc(ranges_size*8);
+	if (!ranges)
+		die("unrecoverable error: can't alloc %d bytes for ranges.\n",
+		    ranges_size*8);
+
+	rlen = 0;
+	for (i = 0; i < num_of_lmbs; i++) {
+		if (read(fd, buf, 24) < 0)
+			die("unrecoverable error: error reading \"%s\": %s\n",
+				pathname, strerror(errno));
+
+		base = (uint64_t) buf[0];
+		end = base + lmb_size;
+		if (~0ULL - base < end)
+			die("unrecoverable error: mem property overflow\n");
+
+		tmp_indx = rlen++;
+
+		rngs_cnt = 0;
+		for (range = 0; range < usablemem_rgns.size; range++) {
+			int add = 0;
+			loc_base = usablemem_rgns.ranges[range].start;
+			loc_end = usablemem_rgns.ranges[range].end;
+			if (loc_base >= base && loc_end <= end) {
+				add = 1;
+			} else if (base < loc_end && end > loc_base) {
+				if (loc_base < base)
+					loc_base = base;
+				if (loc_end > end)
+					loc_end = end;
+				add = 1;
+			}
+
+			if (add) {
+				if (rlen >= (ranges_size-2)) {
+					ranges_size += MEM_RANGE_CHUNK_SZ;
+					ranges = realloc(ranges, ranges_size*8);
+					if (!ranges)
+						die("unrecoverable error: can't"
+						    " realloc %d bytes for"
+						    " ranges.\n",
+						    ranges_size*8);
+				}
+				ranges[rlen++] = loc_base;
+				ranges[rlen++] = loc_end - loc_base;
+				rngs_cnt++;
+			}
+		}
+		if (rngs_cnt == 0) {
+			/* We still need to add a counter for every LMB because
+			 * the kernel parsing code is dumb.  We just have
+			 * a zero in this case, with no following base/len.
+			 */
+			ranges[tmp_indx] = 0;
+			/* rlen is already just tmp_indx+1 as we didn't write
+			 * anything.  Check array size here, as we'll probably
+			 * go on for a while writing zeros now.
+			 */
+			if (rlen >= (ranges_size-1)) {
+				ranges_size += MEM_RANGE_CHUNK_SZ;
+				ranges = realloc(ranges, ranges_size*8);
+				if (!ranges)
+					die("unrecoverable error: can't"
+					    " realloc %d bytes for"
+					    " ranges.\n",
+					    ranges_size*8);
+			}
+		} else {
+			/* Store the count of (base, size) duple */
+			ranges[tmp_indx] = rngs_cnt;
+		}
+	}
+		
+	rlen = rlen * sizeof(uint64_t);
+	/*
+	 * Add linux,drconf-usable-memory property.
+	 */
+	dt_reserve(&dt, 4+((rlen + 3)/4));
+	*dt++ = cpu_to_be32(3);
+	*dt++ = cpu_to_be32(rlen);
+	*dt++ = cpu_to_be32(propnum("linux,drconf-usable-memory"));
+	pad_structure_block(rlen);
+	memcpy(dt, ranges, rlen);
+	free(ranges);
+	dt += cpu_to_be32((rlen + 3)/4);
+}
+
+static void add_dyn_reconf_usable_mem_property(struct dirent *dp, int fd)
+{
+	if (!strcmp(dp->d_name, "ibm,dynamic-memory") && usablemem_rgns.size)
+		add_dyn_reconf_usable_mem_property__(fd);
+}
+#else
+static void add_dyn_reconf_usable_mem_property(struct dirent *dp, int fd) {}
+#endif
+
+static void add_usable_mem_property(int fd, size_t len)
+{
+	char fname[MAXPATH], *bname;
+	uint32_t buf[2];
+	uint32_t *ranges;
+	int ranges_size = MEM_RANGE_CHUNK_SZ;
+	uint64_t base, end, loc_base, loc_end;
+	size_t range;
+	int rlen = 0;
+
+	strcpy(fname, pathname);
+	bname = strrchr(fname,'/');
+	bname[0] = '\0';
+	bname = strrchr(fname,'/');
+	if (strncmp(bname, "/memory@", 8) && strcmp(bname, "/memory"))
+		return;
+
+	if (len < sizeof(buf))
+		die("unrecoverable error: not enough data for mem property\n");
+
+	if (lseek(fd, 0, SEEK_SET) < 0)
+		die("unrecoverable error: error seeking in \"%s\": %s\n",
+		    pathname, strerror(errno));
+	if (read(fd, buf, sizeof(buf)) != sizeof(buf))
+		die("unrecoverable error: error reading \"%s\": %s\n",
+		    pathname, strerror(errno));
+
+	if (~0ULL - buf[0] < buf[1])
+		die("unrecoverable error: mem property overflow\n");
+	base = be32_to_cpu(buf[0]);
+	end = base + be32_to_cpu(buf[1]);
+
+	ranges = malloc(ranges_size * sizeof(*ranges));
+	if (!ranges)
+		die("unrecoverable error: can't alloc %d bytes for ranges.\n",
+		    ranges_size * sizeof(*ranges));
+
+	for (range = 0; range < usablemem_rgns.size; range++) {
+		int add = 0;
+		loc_base = usablemem_rgns.ranges[range].start;
+		loc_end = usablemem_rgns.ranges[range].end;
+		if (loc_base >= base && loc_end <= end) {
+			add = 1;
+		} else if (base < loc_end && end > loc_base) {
+			if (loc_base < base)
+				loc_base = base;
+			if (loc_end > end)
+				loc_end = end;
+			add = 1;
+		}
+		if (add) {
+			if (rlen >= (ranges_size-2)) {
+				ranges_size += MEM_RANGE_CHUNK_SZ;
+				ranges = realloc(ranges, ranges_size *
+						 sizeof(*ranges));
+				if (!ranges)
+					die("unrecoverable error: can't realloc"
+					    "%d bytes for ranges.\n",
+					    ranges_size*sizeof(*ranges));
+			}
+			ranges[rlen++] = loc_base;
+			ranges[rlen++] = loc_end - loc_base;
+		}
+	}
+
+	if (!rlen) {
+		/*
+		 * User did not pass any ranges for thsi region. Hence, write
+		 * (0,0) duple in linux,usable-memory property such that
+		 * this region will be ignored.
+		 */
+		ranges[rlen++] = 0;
+		ranges[rlen++] = 0;
+	}
+
+	rlen = rlen * sizeof(*ranges);
+	/*
+	 * No add linux,usable-memory property.
+	 */
+	dt_reserve(&dt, 4+((rlen + 3)/4));
+	*dt++ = cpu_to_be32(3);
+	*dt++ = cpu_to_be32(rlen);
+	*dt++ = cpu_to_be32(propnum("linux,usable-memory"));
+	pad_structure_block(rlen);
+	memcpy(dt, ranges, rlen);
+	free(ranges);
+	dt += (rlen + 3)/4;
+}
+
+/* put all properties (files) in the property structure */
+static void putprops(char *fn, struct dirent **nlist, int numlist)
+{
+	struct dirent *dp;
+	int i = 0, fd;
+	size_t len;
+	ssize_t slen;
+	struct stat statbuf;
+
+	for (i = 0; i < numlist; i++) {
+		dp = nlist[i];
+		strcpy(fn, dp->d_name);
+
+		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
+                        continue;
+
+		/* Empirically, this seems to need to be ecluded.
+		 * Observed on ARM with 3.6-rc2 kernel
+		 */
+		if (!strcmp(dp->d_name, "name"))
+                        continue;
+
+		if (lstat(pathname, &statbuf))
+			die("unrecoverable error: could not stat \"%s\": %s\n",
+			    pathname, strerror(errno));
+
+		if (!crash_param && !strcmp(fn,"linux,crashkernel-base"))
+			continue;
+
+		if (!crash_param && !strcmp(fn,"linux,crashkernel-size"))
+			continue;
+
+		/*
+		 * This property will be created for each node during kexec
+		 * boot. So, ignore it.
+		 */
+		if (!strcmp(dp->d_name, "linux,pci-domain") ||
+			!strcmp(dp->d_name, "linux,htab-base") ||
+			!strcmp(dp->d_name, "linux,htab-size") ||
+			!strcmp(dp->d_name, "linux,kernel-end"))
+				continue;
+
+		/* This property will be created/modified later in putnode()
+		 * So ignore it, unless we are reusing the initrd.
+		 */
+		if ((!strcmp(dp->d_name, "linux,initrd-start") ||
+		     !strcmp(dp->d_name, "linux,initrd-end")) &&
+		    !reuse_initrd)
+				continue;
+
+		/* This property will be created later in putnode() So
+		 * ignore it now.
+		 */
+		if (!strcmp(dp->d_name, "bootargs"))
+			continue;
+
+		if (! S_ISREG(statbuf.st_mode))
+			continue;
+
+		len = statbuf.st_size;
+
+		dt_reserve(&dt, 4+((len + 3)/4));
+		*dt++ = cpu_to_be32(3);
+		*dt++ = cpu_to_be32(len);
+		*dt++ = cpu_to_be32(propnum(fn));
+		pad_structure_block(len);
+
+		fd = open(pathname, O_RDONLY);
+		if (fd == -1)
+			die("unrecoverable error: could not open \"%s\": %s\n",
+			    pathname, strerror(errno));
+
+		slen = read(fd, dt, len);
+		if (slen < 0)
+			die("unrecoverable error: could not read \"%s\": %s\n",
+			    pathname, strerror(errno));
+		if ((size_t)slen != len)
+			die("unrecoverable error: short read from\"%s\"\n",
+			    pathname);
+
+		checkprop(fn, dt, len);
+
+		dt += (len + 3)/4;
+
+		if (!strcmp(dp->d_name, "reg") && usablemem_rgns.size)
+			add_usable_mem_property(fd, len);
+		add_dyn_reconf_usable_mem_property(dp, fd);
+		close(fd);
+	}
+
+	fn[0] = '\0';
+	checkprop(pathname, NULL, 0);
+}
+
+/*
+ * Compare function used to sort the device-tree directories
+ * This function will be passed to scandir.
+ */
+static int comparefunc(const struct dirent **dentry1,
+		       const struct dirent **dentry2)
+{
+	char *str1 = (*(struct dirent **)dentry1)->d_name;
+	char *str2 = (*(struct dirent **)dentry2)->d_name;
+
+	/*
+	 * strcmp scans from left to right and fails to idetify for some
+	 * strings such as memory at 10000000 and memory at f000000.
+	 * Therefore, we get the wrong sorted order like memory at 10000000 and
+	 * memory at f000000.
+	 */
+	if (strchr(str1, '@') && strchr(str2, '@') &&
+		(strlen(str1) > strlen(str2)))
+		return 1;
+
+	return strcmp(str1, str2);
+}
+
+/*
+ * put a node (directory) in the property structure.  first properties
+ * then children.
+ */
+static void putnode(void)
+{
+	char *dn;
+	struct dirent *dp;
+	char *basename;
+	struct dirent **namelist;
+	int numlist, i;
+	struct stat statbuf;
+	int plen;
+
+	numlist = scandir(pathname, &namelist, 0, comparefunc);
+	if (numlist < 0)
+		die("unrecoverable error: could not scan \"%s\": %s\n",
+		    pathname, strerror(errno));
+	if (numlist == 0)
+		die("unrecoverable error: no directory entries in \"%s\"",
+		    pathname);
+
+	basename = strrchr(pathname,'/') + 1;
+
+	plen = *basename ? strlen(basename) : 0;
+	/* Reserve space for string packed to words; e.g. string length 10
+	 * occupies 3 words, length 12 occupies 4 (for terminating \0s).
+	 * So round up & include the \0:
+	 */
+	dt_reserve(&dt, 1+((plen + 4)/4));
+	*dt++ = cpu_to_be32(1);
+	strcpy((void *)dt, *basename ? basename : "");
+	dt += ((plen + 4)/4);
+
+	strcat(pathname, "/");
+	dn = pathname + strlen(pathname);
+
+	putprops(dn, namelist, numlist);
+
+	/* Add initrd entries to the second kernel */
+	if (initrd_base && !strcmp(basename,"/chosen/")) {
+		int len = 8;
+		unsigned long long initrd_end;
+
+		dt_reserve(&dt, 12); /* both props, of 6 words ea. */
+		*dt++ = cpu_to_be32(3);
+		*dt++ = cpu_to_be32(len);
+		*dt++ = cpu_to_be32(propnum("linux,initrd-start"));
+		pad_structure_block(len);
+
+		memcpy(dt,&initrd_base,len);
+		dt += (len + 3)/4;
+
+		len = 8;
+		*dt++ = cpu_to_be32(3);
+		*dt++ = cpu_to_be32(len);
+		*dt++ = cpu_to_be32(propnum("linux,initrd-end"));
+
+		initrd_end = initrd_base + initrd_size;
+		pad_structure_block(len);
+
+		memcpy(dt,&initrd_end,len);
+		dt += (len + 3)/4;
+
+		reserve(initrd_base, initrd_size);
+	}
+
+	/* Add cmdline to the second kernel.  Check to see if the new
+	 * cmdline has a root=.  If not, use the old root= cmdline.  */
+	if (!strcmp(basename,"/chosen/")) {
+		size_t cmd_len = 0;
+		char *param = NULL;
+		char filename[MAXPATH];
+		char *buff;
+		int fd;
+
+		cmd_len = strlen(local_cmdline);
+		if (cmd_len != 0) {
+			param = strstr(local_cmdline, "crashkernel=");
+			if (param)
+				crash_param = 1;
+			/* does the new cmdline have a root= ? ... */
+			param = strstr(local_cmdline, "root=");
+		}
+
+		/* ... if not, grab root= from the old command line */
+		if (!param) {
+			FILE *fp;
+			char *last_cmdline = NULL;
+			char *old_param;
+
+			strcpy(filename, pathname);
+			strcat(filename, "bootargs");
+			fp = fopen(filename, "r");
+			if (fp) {
+				if (getline(&last_cmdline, &cmd_len, fp) == -1)
+					die("unable to read %s\n", filename);
+
+				param = strstr(last_cmdline, "root=");
+				if (param) {
+					old_param = strtok(param, " ");
+					if (cmd_len != 0)
+						strcat(local_cmdline, " ");
+					strcat(local_cmdline, old_param);
+				}
+			}
+			if (last_cmdline)
+				free(last_cmdline);
+		}
+		strcat(local_cmdline, " ");
+		cmd_len = strlen(local_cmdline);
+		cmd_len = cmd_len + 1;
+
+		/* add new bootargs */
+		dt_reserve(&dt, 4+((cmd_len+3)/4));
+		*dt++ = cpu_to_be32(3);
+		*dt++ = cpu_to_be32(cmd_len);
+		*dt++ = cpu_to_be32(propnum("bootargs"));
+		pad_structure_block(cmd_len);
+		memcpy(dt, local_cmdline,cmd_len);
+		dt += (cmd_len + 3)/4;
+
+		fprintf(stderr, "Modified cmdline:%s\n", local_cmdline);
+
+		/*
+		 * Determine the platform type/stdout type, so that purgatory
+		 * code can print 'I'm in purgatory' message. Currently only
+		 * pseries/hvcterminal is supported.
+		 */
+		strcpy(filename, pathname);
+		strncat(filename, "linux,stdout-path", MAXPATH);
+		fd = open(filename, O_RDONLY);
+		if (fd == -1) {
+			printf("Unable to find %s, printing from purgatory is diabled\n",
+														filename);
+			goto no_debug;
+		}
+		if (fstat(fd, &statbuf)) {
+			printf("Unable to stat %s, printing from purgatory is diabled\n",
+														filename);
+			close(fd);
+			goto no_debug;
+
+		}
+
+		buff = malloc(statbuf.st_size);
+		if (!buff) {
+			printf("Can not allocate memory for buff\n");
+			close(fd);
+			goto no_debug;
+		}
+		read(fd, buff, statbuf.st_size);
+		close(fd);
+		strncpy(filename, "/proc/device-tree/", MAXPATH);
+		strncat(filename, buff, MAXPATH);
+		strncat(filename, "/compatible", MAXPATH);
+		fd = open(filename, O_RDONLY);
+		if (fd == -1) {
+			printf("Unable to find %s printing from purgatory is diabled\n",
+														filename);
+			goto no_debug;
+		}
+		if (fstat(fd, &statbuf)) {
+			printf("Unable to stat %s printing from purgatory is diabled\n",
+														filename);
+			close(fd);
+			goto no_debug;
+		}
+		buff = realloc(buff, statbuf.st_size);
+		if (!buff) {
+			printf("Can not allocate memory for buff\n");
+			close(fd);
+			goto no_debug;
+		}
+		read(fd, buff, statbuf.st_size);
+		if (!strcmp(buff, "hvterm1") || !strcmp(buff, "hvterm-protocol"))
+			my_debug = 1;
+		close(fd);
+		free(buff);
+	}
+
+no_debug:
+	for (i=0; i < numlist; i++) {
+		dp = namelist[i];
+		strcpy(dn, dp->d_name);
+		free(namelist[i]);
+
+		if (!strcmp(dn, ".") || !strcmp(dn, ".."))
+			continue;
+
+		if (lstat(pathname, &statbuf))
+			die("unrecoverable error: could not stat \"%s\": %s\n",
+			    pathname, strerror(errno));
+
+		if (S_ISDIR(statbuf.st_mode))
+			putnode();
+	}
+
+	dt_reserve(&dt, 1);
+	*dt++ = cpu_to_be32(2);
+	dn[-1] = '\0';
+	free(namelist);
+}
+
+struct bootblock bb[1];
+
+static void add_boot_block(char **bufp, off_t *sizep)
+{
+	unsigned long len;
+	unsigned long tlen, toff;
+	char *buf;
+
+	len = sizeof(bb[0]);
+	len += 7; len &= ~7;
+
+	bb->off_mem_rsvmap = cpu_to_be32(len);
+
+	for (len = 1; be64_to_cpu(mem_rsrv[len]); len += 2)
+		;
+	len++;
+#ifdef NEED_RESERVE_DTB
+	len+= 3; /* Leave space for totalsize reservation */
+#endif
+	len *= sizeof(mem_rsrv[0]);
+
+	bb->off_dt_struct = cpu_to_be32(be32_to_cpu(bb->off_mem_rsvmap) + len);
+
+	len = dt - dt_base;
+	len *= sizeof(unsigned);
+#if (BOOT_BLOCK_VERSION >= 17)
+	bb->dt_struct_size = cpu_to_be32(len);
+#endif
+	bb->off_dt_strings = cpu_to_be32(be32_to_cpu(bb->off_dt_struct) + len);
+
+	len = propnum("");
+	bb->dt_strings_size = cpu_to_be32(len);
+	len +=  3; len &= ~3;
+	bb->totalsize = cpu_to_be32(be32_to_cpu(bb->off_dt_strings) + len);
+
+	bb->magic = cpu_to_be32(0xd00dfeed);
+	bb->version = cpu_to_be32(BOOT_BLOCK_VERSION);
+	bb->last_comp_version = cpu_to_be32(BOOT_BLOCK_LAST_COMP_VERSION);
+
+#ifdef NEED_RESERVE_DTB
+	reserve(0, be32_to_cpu(bb->totalsize)); /* patched later in kexec_load */
+#endif
+
+	buf = malloc(be32_to_cpu(bb->totalsize));
+	*bufp = buf;
+
+	tlen = be32_to_cpu(bb->off_mem_rsvmap);
+	memcpy(buf, bb, tlen);
+
+	toff = be32_to_cpu(bb->off_mem_rsvmap);
+	tlen = be32_to_cpu(bb->off_dt_struct) - be32_to_cpu(bb->off_mem_rsvmap);
+	memcpy(buf + toff, mem_rsrv, tlen);
+
+	toff += be32_to_cpu(bb->off_dt_struct) - be32_to_cpu(bb->off_mem_rsvmap);
+	tlen = be32_to_cpu(bb->off_dt_strings) - be32_to_cpu(bb->off_dt_struct);
+	memcpy(buf + toff, dt_base,  tlen);
+
+	toff += be32_to_cpu(bb->off_dt_strings) - be32_to_cpu(bb->off_dt_struct);
+	tlen = be32_to_cpu(bb->totalsize) - be32_to_cpu(bb->off_dt_strings);
+	memcpy(buf + toff, propnames,  tlen);
+
+	*sizep = toff + be32_to_cpu(bb->totalsize) -
+		be32_to_cpu(bb->off_dt_strings);
+}
+
+void create_flatten_tree(char **bufp, off_t *sizep, const char *cmdline)
+{
+	strcpy(pathname, "/proc/device-tree/");
+
+	pathstart = pathname + strlen(pathname);
+
+	dt_cur_size = INIT_TREE_WORDS;
+	dt_base = malloc(dt_cur_size*4);
+	if (!dt_base) {
+		die("Can't malloc %d bytes for dt struct!\n", dt_cur_size*4);
+	}
+	memset(dt_base, 0, dt_cur_size*4);
+
+	dt = dt_base;
+
+	if (cmdline)
+		strcpy(local_cmdline, cmdline);
+
+	putnode();
+	dt_reserve(&dt, 1);
+	*dt++ = cpu_to_be32(9);
+
+	add_boot_block(bufp, sizep);
+	free(dt_base);
+}
diff --git a/kexec/fs2dt.h b/kexec/fs2dt.h
new file mode 100644
index 0000000..6c5c3b2
--- /dev/null
+++ b/kexec/fs2dt.h
@@ -0,0 +1,38 @@
+#ifndef FS2DT_H
+#define FS2DT_H
+
+#if (BOOT_BLOCK_VERSION != 2 && BOOT_BLOCK_VERSION != 17)
+#error Please add or correct definition of BOOT_BLOCK_VERSION
+#endif
+
+/* boot block as defined by the linux kernel */
+struct bootblock {
+	unsigned magic;
+	unsigned totalsize;
+	unsigned off_dt_struct;
+	unsigned off_dt_strings;
+	unsigned off_mem_rsvmap;
+	unsigned version;
+	unsigned last_comp_version;
+#if (BOOT_BLOCK_VERSION >= 2)
+	/* version 2 fields below */
+	unsigned boot_physid;
+	/* version 3 fields below */
+	unsigned dt_strings_size;
+#if (BOOT_BLOCK_VERSION >= 17)
+	/* version 17 fields below */
+	unsigned dt_struct_size;
+#endif
+#endif
+};
+
+extern struct bootblock bb[1];
+
+/* Used for enabling printing message from purgatory code
+ * Only has implemented for PPC64 */
+int my_debug;
+
+void reserve(unsigned long long where, unsigned long long length);
+void create_flatten_tree(char **, off_t *, const char *);
+
+#endif /* KEXEC_H */
diff --git a/kexec/kexec.h b/kexec/kexec.h
index d24b3fa..1f46bcb 100644
--- a/kexec/kexec.h
+++ b/kexec/kexec.h
@@ -126,6 +126,11 @@ struct memory_range {
 #define RANGE_UNCACHED	4
 };
 
+struct memory_ranges {
+        unsigned int size;
+        struct memory_range *ranges;
+};
+
 struct kexec_info {
 	struct kexec_segment *segment;
 	int nr_segments;
-- 
1.7.12



From matthew.leach at arm.com  Fri Sep  7 05:11:26 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Fri,  7 Sep 2012 10:11:26 +0100
Subject: [PATCH 7/7] ARM: Add device tree support to the ARM platform
In-Reply-To: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
References: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
Message-ID: <1347009086-16506-8-git-send-email-matthew.leach@arm.com>

To allow newer ARM platforms to use kexec, pass device tree
information to the kernel during boot.

By default the dtb is found from /proc/device-tree. A user can specify
a dtb file or use legacy ATAGs

Signed-off-by: Matthew Leach <matthew.leach at arm.com>
---
 kexec/arch/arm/Makefile               | 13 ++++++
 kexec/arch/arm/include/arch/options.h |  6 ++-
 kexec/arch/arm/kexec-arm.h            |  7 +++
 kexec/arch/arm/kexec-zImage-arm.c     | 87 +++++++++++++++++++++++++++++++----
 4 files changed, 103 insertions(+), 10 deletions(-)

diff --git a/kexec/arch/arm/Makefile b/kexec/arch/arm/Makefile
index 288ec33..192e6ec 100644
--- a/kexec/arch/arm/Makefile
+++ b/kexec/arch/arm/Makefile
@@ -1,11 +1,24 @@
 #
 # kexec arm (linux booting linux)
 #
+include $(srcdir)/kexec/libfdt/Makefile.libfdt
+
+arm_FS2DT              = kexec/fs2dt.c
+arm_FS2DT_INCLUDE      = -include kexec/arch/arm/crashdump-arm.h \
+                         -include kexec/arch/arm/kexec-arm.h
+
 arm_KEXEC_SRCS=  kexec/arch/arm/kexec-elf-rel-arm.c
 arm_KEXEC_SRCS+= kexec/arch/arm/kexec-zImage-arm.c
 arm_KEXEC_SRCS+= kexec/arch/arm/kexec-uImage-arm.c
 arm_KEXEC_SRCS+= kexec/arch/arm/kexec-arm.c
 arm_KEXEC_SRCS+= kexec/arch/arm/crashdump-arm.c
+arm_KEXEC_SRCS+= kexec/fs2dt.c
+
+libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%)
+
+CPPFLAGS+=-I$(srcdir)/kexec/libfdt
+
+arm_KEXEC_SRCS += $(libfdt_SRCS)
 
 arm_UIMAGE = kexec/kexec-uImage.c
 arm_PHYS_TO_VIRT = kexec/arch/arm/phys_to_virt.c
diff --git a/kexec/arch/arm/include/arch/options.h b/kexec/arch/arm/include/arch/options.h
index d89c91f..b355c26 100644
--- a/kexec/arch/arm/include/arch/options.h
+++ b/kexec/arch/arm/include/arch/options.h
@@ -5,6 +5,8 @@
 
 #define OPT_APPEND	'a'
 #define OPT_RAMDISK	'r'
+#define OPT_DTB     (OPT_ARCH_MAX+0)
+#define OPT_ATAGS   (OPT_ARCH_MAX+1)
 
 /* Options relevant to the architecture (excluding loader-specific ones),
  * in this case none:
@@ -33,7 +35,9 @@
 	{ "command-line",	1, 0, OPT_APPEND },	\
 	{ "append",		1, 0, OPT_APPEND },	\
 	{ "initrd",		1, 0, OPT_RAMDISK },	\
-	{ "ramdisk",		1, 0, OPT_RAMDISK },
+	{ "ramdisk",		1, 0, OPT_RAMDISK },	\
+	{ "dtb",		1, 0, OPT_DTB }, 	\
+	{ "atags",		0, 0, OPT_ATAGS },
 
 #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR "a:r:"
 
diff --git a/kexec/arch/arm/kexec-arm.h b/kexec/arch/arm/kexec-arm.h
index 0d9a066..79663e3 100644
--- a/kexec/arch/arm/kexec-arm.h
+++ b/kexec/arch/arm/kexec-arm.h
@@ -1,6 +1,13 @@
 #ifndef KEXEC_ARM_H
 #define KEXEC_ARM_H
 
+#include <sys/types.h>
+
+#define BOOT_BLOCK_VERSION 17
+#define BOOT_BLOCK_LAST_COMP_VERSION 16
+
+extern off_t initrd_base, initrd_size;
+
 int zImage_arm_probe(const char *buf, off_t len);
 int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 		        struct kexec_info *info);
diff --git a/kexec/arch/arm/kexec-zImage-arm.c b/kexec/arch/arm/kexec-zImage-arm.c
index 88a6c29..46cedbf 100644
--- a/kexec/arch/arm/kexec-zImage-arm.c
+++ b/kexec/arch/arm/kexec-zImage-arm.c
@@ -13,13 +13,18 @@
 #include <unistd.h>
 #include <getopt.h>
 #include <unistd.h>
+#include <libfdt.h>
 #include <arch/options.h>
 #include "../../kexec.h"
 #include "../../kexec-syscall.h"
+#include "kexec-arm.h"
+#include "../../fs2dt.h"
 #include "crashdump-arm.h"
 
 #define BOOT_PARAMS_SIZE 1536
 
+off_t initrd_base = 0, initrd_size = 0;
+
 struct tag_header {
 	uint32_t size;
 	uint32_t tag;
@@ -96,6 +101,8 @@ void zImage_arm_usage(void)
 		"     --append=STRING       Set the kernel command line to STRING.\n"
 		"     --initrd=FILE         Use FILE as the kernel's initial ramdisk.\n"
 		"     --ramdisk=FILE        Use FILE as the kernel's initial ramdisk.\n"
+		"     --dtb=FILE            Use FILE as the fdt blob.\n"
+		"     --atags               Use ATAGs instead of device-tree.\n"
 		);
 }
 
@@ -219,9 +226,13 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 	off_t command_line_len;
 	const char *ramdisk;
 	char *ramdisk_buf;
-	off_t ramdisk_length;
-	off_t ramdisk_offset;
 	int opt;
+	int use_atags;
+	char *dtb_buf;
+	off_t dtb_length;
+	char *dtb_file;
+	off_t dtb_offset;
+
 	/* See options.h -- add any more there, too. */
 	static const struct option options[] = {
 		KEXEC_ARCH_OPTIONS
@@ -229,6 +240,8 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 		{ "append",		1, 0, OPT_APPEND },
 		{ "initrd",		1, 0, OPT_RAMDISK },
 		{ "ramdisk",		1, 0, OPT_RAMDISK },
+		{ "dtb",		1, 0, OPT_DTB },
+		{ "atags",		0, 0, OPT_ATAGS },
 		{ 0, 			0, 0, 0 },
 	};
 	static const char short_options[] = KEXEC_ARCH_OPT_STR "a:r:";
@@ -240,7 +253,9 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 	command_line_len = 0;
 	ramdisk = 0;
 	ramdisk_buf = 0;
-	ramdisk_length = 0;
+	initrd_size = 0;
+	use_atags = 0;
+	dtb_file = NULL;
 	while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) {
 		switch(opt) {
 		default:
@@ -257,15 +272,28 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 		case OPT_RAMDISK:
 			ramdisk = optarg;
 			break;
+		case OPT_DTB:
+			dtb_file = optarg;
+			break;
+		case OPT_ATAGS:
+			use_atags = 1;
+			break;
 		}
 	}
+
+	if (use_atags && dtb_file) {
+		fprintf(stderr, "You can only use ATAGs if you don't specify a "
+		        "dtb file.\n");
+		return -1;
+	}
+
 	if (command_line) {
 		command_line_len = strlen(command_line) + 1;
 		if (command_line_len > COMMAND_LINE_SIZE)
 			command_line_len = COMMAND_LINE_SIZE;
 	}
 	if (ramdisk) {
-		ramdisk_buf = slurp_file(ramdisk, &ramdisk_length);
+		ramdisk_buf = slurp_file(ramdisk, &initrd_size);
 	}
 
 	/*
@@ -315,12 +343,53 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len,
 	/* assume the maximum kernel compression ratio is 4,
 	 * and just to be safe, place ramdisk after that
 	 */
-	ramdisk_offset = base + len * 4;
+	initrd_base = base + len * 4;
 
-	if (atag_arm_load(info, base + atag_offset,
-			 command_line, command_line_len,
-			 ramdisk_buf, ramdisk_length, ramdisk_offset) == -1)
-		return -1;
+	if (use_atags) {
+		/*
+		 * use ATAGs from /proc/atags
+		 */
+		if (atag_arm_load(info, base + atag_offset,
+		                  command_line, command_line_len,
+		                  ramdisk_buf, initrd_size, initrd_base) == -1)
+			return -1;
+	} else {
+		/*
+		 * Read a user-specified DTB file.
+		 */
+		if (dtb_file) {
+			dtb_buf = slurp_file(dtb_file, &dtb_length);
+		} else {
+			/*
+			 * Extract the DTB from /proc/device-tree.
+			 */
+			create_flatten_tree(&dtb_buf, &dtb_length, command_line);
+		}
+
+		if (fdt_check_header(dtb_buf) != 0) {
+			fprintf(stderr, "Invalid FDT buffer.\n");
+			return -1;
+		}
+
+		if (base + atag_offset + dtb_length > base + offset) {
+			fprintf(stderr, "DTB too large!\n");
+			return -1;
+		}
+
+		if (ramdisk) {
+			add_segment(info, ramdisk_buf, initrd_size,
+			            initrd_base, initrd_size);
+		}
+
+		/* Stick the dtb at the end of the initrd and page
+		 * align it.
+		 */
+		dtb_offset = initrd_base + initrd_size + getpagesize();
+		dtb_offset &= ~(getpagesize() - 1);
+
+		add_segment(info, dtb_buf, dtb_length,
+		            dtb_offset, dtb_length);
+	}
 
 	add_segment(info, buf, len, base + offset, len);
 
-- 
1.7.12



From matthew.leach at arm.com  Fri Sep  7 05:11:19 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Fri,  7 Sep 2012 10:11:19 +0100
Subject: [PATCH 0/7] Add device-tree support to kexec-tools for ARM
Message-ID: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>

Hi all,

Running a kexec() on ARM platforms has become an issue as information
about the platform that is presented via device-tree is required to
boot newer kernels.

The ATAGs kernel code is re-used, replacing the ATAGs with a
device-tree blob so that only kexec-tools needs to be changed. There
are two options for generating a dtb to be passed to the kernel from
kexec-tools: 1) Read in the device-tree that is exposed in
/proc/device-tree and flatten this out into a dtb.  2) Allow the user
to specify a dtb file on the command line.  These blobs are then
loaded into memory before the kernel image and the address passed
through to r2, as stated in the ARM booting documentation.

These patches depend upon a kernel patch, namely:
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-September/118275.html

Simon - you are welcome to add your signed-off-by to my final patch as
I incorporated bits of your final patch into mine.

Matt

Matthew Leach (1):
  ARM: Add device tree support to the ARM platform

Simon Horman (6):
  libfdt: Move from kexec/arch/ppc/libfdt/ to kexec/libfdt/
  kexec-elf.h: Include headers for types used
  fs2dt: Add a generic copy of fs2dt
  ppc64: Move 64bit powerpc to use generic fs2dt code
  powerpc: Move 32bit powerpc to use generic fs2dt code
  arm: Make use of memory_ranges

 kexec/Makefile                                |   6 +
 kexec/arch/arm/Makefile                       |  13 +
 kexec/arch/arm/crashdump-arm.c                |  45 ++-
 kexec/arch/arm/crashdump-arm.h                |   2 +
 kexec/arch/arm/include/arch/options.h         |   6 +-
 kexec/arch/arm/kexec-arm.h                    |   7 +
 kexec/arch/arm/kexec-zImage-arm.c             |  87 ++++-
 kexec/arch/ppc/Makefile                       |  17 +-
 kexec/arch/ppc/crashdump-powerpc.c            |   2 +-
 kexec/arch/ppc/crashdump-powerpc.h            |   2 +
 kexec/arch/ppc/fs2dt.c                        | 450 --------------------------
 kexec/arch/ppc/kexec-elf-ppc.c                |   2 -
 kexec/arch/ppc/kexec-ppc.h                    |  26 +-
 kexec/arch/ppc/kexec-uImage-ppc.c             |   3 -
 kexec/arch/ppc64/Makefile                     |   7 +-
 kexec/arch/ppc64/crashdump-ppc64.c            |   3 +-
 kexec/arch/ppc64/crashdump-ppc64.h            |   4 +
 kexec/arch/ppc64/kexec-elf-ppc64.c            |   4 +-
 kexec/arch/ppc64/kexec-ppc64.c                |   1 +
 kexec/arch/ppc64/kexec-ppc64.h                |  29 +-
 kexec/arch_reuse_initrd.c                     |   2 +
 kexec/{arch/ppc64 => }/fs2dt.c                | 277 +++++++++-------
 kexec/fs2dt.h                                 |  38 +++
 kexec/kexec-elf.h                             |   3 +
 kexec/kexec.h                                 |   5 +
 kexec/{arch/ppc => }/libfdt/Makefile.libfdt   |   8 +-
 kexec/{arch/ppc => }/libfdt/TODO              |   0
 kexec/{arch/ppc => }/libfdt/fdt.c             |   0
 kexec/{arch/ppc => }/libfdt/fdt.h             |   0
 kexec/{arch/ppc => }/libfdt/fdt_ro.c          |   0
 kexec/{arch/ppc => }/libfdt/fdt_rw.c          |   0
 kexec/{arch/ppc => }/libfdt/fdt_strerror.c    |   0
 kexec/{arch/ppc => }/libfdt/fdt_sw.c          |   0
 kexec/{arch/ppc => }/libfdt/fdt_wip.c         |   0
 kexec/{arch/ppc => }/libfdt/libfdt.h          |   0
 kexec/{arch/ppc => }/libfdt/libfdt_env.h      |   0
 kexec/{arch/ppc => }/libfdt/libfdt_internal.h |   0
 37 files changed, 392 insertions(+), 657 deletions(-)
 delete mode 100644 kexec/arch/ppc/fs2dt.c
 rename kexec/{arch/ppc64 => }/fs2dt.c (77%)
 create mode 100644 kexec/fs2dt.h
 rename kexec/{arch/ppc => }/libfdt/Makefile.libfdt (60%)
 rename kexec/{arch/ppc => }/libfdt/TODO (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt.c (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt.h (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt_ro.c (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt_rw.c (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt_strerror.c (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt_sw.c (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt_wip.c (100%)
 rename kexec/{arch/ppc => }/libfdt/libfdt.h (100%)
 rename kexec/{arch/ppc => }/libfdt/libfdt_env.h (100%)
 rename kexec/{arch/ppc => }/libfdt/libfdt_internal.h (100%)

-- 
1.7.12



From matthew.leach at arm.com  Fri Sep  7 05:11:21 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Fri,  7 Sep 2012 10:11:21 +0100
Subject: [PATCH 2/7] kexec-elf.h: Include headers for types used
In-Reply-To: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
References: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
Message-ID: <1347009086-16506-3-git-send-email-matthew.leach@arm.com>

From: Simon Horman <horms at verge.net.au>

Signed-off-by: Simon Horman <horms at verge.net.au>
---
 kexec/kexec-elf.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kexec/kexec-elf.h b/kexec/kexec-elf.h
index 99cb80b..d0e9dc0 100644
--- a/kexec/kexec-elf.h
+++ b/kexec/kexec-elf.h
@@ -1,6 +1,9 @@
 #ifndef KEXEC_ELF_H
 #define KEXEC_ELF_H
 
+#include <stdint.h>
+#include <sys/types.h>
+
 struct kexec_info;
 
 struct mem_ehdr {
-- 
1.7.12



From matthew.leach at arm.com  Fri Sep  7 05:11:20 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Fri,  7 Sep 2012 10:11:20 +0100
Subject: [PATCH 1/7] libfdt: Move from kexec/arch/ppc/libfdt/ to kexec/libfdt/
In-Reply-To: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
References: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
Message-ID: <1347009086-16506-2-git-send-email-matthew.leach@arm.com>

From: Simon Horman <horms at verge.net.au>

This is in preparation for using the code on ARM as well as PPC.

Signed-off-by: Simon Horman <horms at verge.net.au>
---
 kexec/arch/ppc/Makefile                       | 10 +++++-----
 kexec/{arch/ppc => }/libfdt/Makefile.libfdt   |  8 ++++----
 kexec/{arch/ppc => }/libfdt/TODO              |  0
 kexec/{arch/ppc => }/libfdt/fdt.c             |  0
 kexec/{arch/ppc => }/libfdt/fdt.h             |  0
 kexec/{arch/ppc => }/libfdt/fdt_ro.c          |  0
 kexec/{arch/ppc => }/libfdt/fdt_rw.c          |  0
 kexec/{arch/ppc => }/libfdt/fdt_strerror.c    |  0
 kexec/{arch/ppc => }/libfdt/fdt_sw.c          |  0
 kexec/{arch/ppc => }/libfdt/fdt_wip.c         |  0
 kexec/{arch/ppc => }/libfdt/libfdt.h          |  0
 kexec/{arch/ppc => }/libfdt/libfdt_env.h      |  0
 kexec/{arch/ppc => }/libfdt/libfdt_internal.h |  0
 13 files changed, 9 insertions(+), 9 deletions(-)
 rename kexec/{arch/ppc => }/libfdt/Makefile.libfdt (60%)
 rename kexec/{arch/ppc => }/libfdt/TODO (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt.c (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt.h (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt_ro.c (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt_rw.c (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt_strerror.c (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt_sw.c (100%)
 rename kexec/{arch/ppc => }/libfdt/fdt_wip.c (100%)
 rename kexec/{arch/ppc => }/libfdt/libfdt.h (100%)
 rename kexec/{arch/ppc => }/libfdt/libfdt_env.h (100%)
 rename kexec/{arch/ppc => }/libfdt/libfdt_internal.h (100%)

diff --git a/kexec/arch/ppc/Makefile b/kexec/arch/ppc/Makefile
index e868917..5225a8f 100644
--- a/kexec/arch/ppc/Makefile
+++ b/kexec/arch/ppc/Makefile
@@ -1,7 +1,7 @@
 #
 # kexec ppc (linux booting linux)
 #
-include $(srcdir)/kexec/arch/ppc/libfdt/Makefile.libfdt
+include $(srcdir)/kexec/libfdt/Makefile.libfdt
 
 ppc_KEXEC_SRCS =  kexec/arch/ppc/kexec-ppc.c
 ppc_KEXEC_SRCS += kexec/arch/ppc/kexec-elf-ppc.c
@@ -16,13 +16,13 @@ ppc_KEXEC_SRCS += kexec/arch/ppc/crashdump-powerpc.c
 
 ppc_UIMAGE = kexec/kexec-uImage.c
 
-libfdt_SRCS = kexec/arch/ppc/libfdt-wrapper.c
-libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/arch/ppc/libfdt/%)
+ppc_libfdt_SRCS = kexec/arch/ppc/libfdt-wrapper.c
+libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%)
 ppc_ARCH_REUSE_INITRD =
 
-CPPFLAGS+=-I$(srcdir)/kexec/arch/$(ARCH)/libfdt
+CPPFLAGS+=-I$(srcdir)/kexec/libfdt
 
-ppc_KEXEC_SRCS += $(libfdt_SRCS)
+ppc_KEXEC_SRCS += $(libfdt_SRCS) $(ppc_libfdt_SRCS)
 
 dist += kexec/arch/ppc/Makefile $(ppc_KEXEC_SRCS)			\
 	kexec/arch/ppc/crashdump-powerpc.h kexec/arch/ppc/fixup_dtb.h	\
diff --git a/kexec/arch/ppc/libfdt/Makefile.libfdt b/kexec/libfdt/Makefile.libfdt
similarity index 60%
rename from kexec/arch/ppc/libfdt/Makefile.libfdt
rename to kexec/libfdt/Makefile.libfdt
index 1d1b295..9a2b4f7 100644
--- a/kexec/arch/ppc/libfdt/Makefile.libfdt
+++ b/kexec/libfdt/Makefile.libfdt
@@ -7,7 +7,7 @@ LIBFDT_INCLUDES = fdt.h libfdt.h
 LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
 
-dist += kexec/arch/ppc/libfdt/Makefile.libfdt				\
-	kexec/arch/ppc/libfdt/fdt.h kexec/arch/ppc/libfdt/libfdt.h	\
-	kexec/arch/ppc/libfdt/libfdt_env.h				\
-	kexec/arch/ppc/libfdt/libfdt_internal.h
+dist += kexec/libfdt/Makefile.libfdt			\
+	kexec/libfdt/fdt.h kexec/libfdt/libfdt.h	\
+	kexec/libfdt/libfdt_env.h			\
+	kexec/libfdt/libfdt_internal.h
diff --git a/kexec/arch/ppc/libfdt/TODO b/kexec/libfdt/TODO
similarity index 100%
rename from kexec/arch/ppc/libfdt/TODO
rename to kexec/libfdt/TODO
diff --git a/kexec/arch/ppc/libfdt/fdt.c b/kexec/libfdt/fdt.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt.c
rename to kexec/libfdt/fdt.c
diff --git a/kexec/arch/ppc/libfdt/fdt.h b/kexec/libfdt/fdt.h
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt.h
rename to kexec/libfdt/fdt.h
diff --git a/kexec/arch/ppc/libfdt/fdt_ro.c b/kexec/libfdt/fdt_ro.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt_ro.c
rename to kexec/libfdt/fdt_ro.c
diff --git a/kexec/arch/ppc/libfdt/fdt_rw.c b/kexec/libfdt/fdt_rw.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt_rw.c
rename to kexec/libfdt/fdt_rw.c
diff --git a/kexec/arch/ppc/libfdt/fdt_strerror.c b/kexec/libfdt/fdt_strerror.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt_strerror.c
rename to kexec/libfdt/fdt_strerror.c
diff --git a/kexec/arch/ppc/libfdt/fdt_sw.c b/kexec/libfdt/fdt_sw.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt_sw.c
rename to kexec/libfdt/fdt_sw.c
diff --git a/kexec/arch/ppc/libfdt/fdt_wip.c b/kexec/libfdt/fdt_wip.c
similarity index 100%
rename from kexec/arch/ppc/libfdt/fdt_wip.c
rename to kexec/libfdt/fdt_wip.c
diff --git a/kexec/arch/ppc/libfdt/libfdt.h b/kexec/libfdt/libfdt.h
similarity index 100%
rename from kexec/arch/ppc/libfdt/libfdt.h
rename to kexec/libfdt/libfdt.h
diff --git a/kexec/arch/ppc/libfdt/libfdt_env.h b/kexec/libfdt/libfdt_env.h
similarity index 100%
rename from kexec/arch/ppc/libfdt/libfdt_env.h
rename to kexec/libfdt/libfdt_env.h
diff --git a/kexec/arch/ppc/libfdt/libfdt_internal.h b/kexec/libfdt/libfdt_internal.h
similarity index 100%
rename from kexec/arch/ppc/libfdt/libfdt_internal.h
rename to kexec/libfdt/libfdt_internal.h
-- 
1.7.12



From matthew.leach at arm.com  Fri Sep  7 05:11:24 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Fri,  7 Sep 2012 10:11:24 +0100
Subject: [PATCH 5/7] powerpc: Move 32bit powerpc to use generic fs2dt code
In-Reply-To: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
References: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
Message-ID: <1347009086-16506-6-git-send-email-matthew.leach@arm.com>

From: Simon Horman <horms at verge.net.au>

Compile tested only

Signed-off-by: Simon Horman <horms at verge.net.au>
---
 kexec/arch/ppc/Makefile            |   7 +-
 kexec/arch/ppc/crashdump-powerpc.c |   2 +-
 kexec/arch/ppc/crashdump-powerpc.h |   2 +
 kexec/arch/ppc/fs2dt.c             | 450 -------------------------------------
 kexec/arch/ppc/kexec-elf-ppc.c     |   2 -
 kexec/arch/ppc/kexec-ppc.h         |  26 +--
 kexec/arch/ppc/kexec-uImage-ppc.c  |   3 -
 7 files changed, 16 insertions(+), 476 deletions(-)
 delete mode 100644 kexec/arch/ppc/fs2dt.c

diff --git a/kexec/arch/ppc/Makefile b/kexec/arch/ppc/Makefile
index 5225a8f..8dcf5f0 100644
--- a/kexec/arch/ppc/Makefile
+++ b/kexec/arch/ppc/Makefile
@@ -3,6 +3,12 @@
 #
 include $(srcdir)/kexec/libfdt/Makefile.libfdt
 
+ppc_FS2DT		= kexec/fs2dt.c
+ppc_FS2DT_INCLUDE	= -include kexec/arch/ppc/crashdump-powerpc.h \
+			  -include kexec/arch/ppc/kexec-ppc.h
+
+ppc_KEXEC_SRCS += kexec/fs2dt.c
+
 ppc_KEXEC_SRCS =  kexec/arch/ppc/kexec-ppc.c
 ppc_KEXEC_SRCS += kexec/arch/ppc/kexec-elf-ppc.c
 ppc_KEXEC_SRCS += kexec/arch/ppc/kexec-elf-rel-ppc.c
@@ -11,7 +17,6 @@ ppc_KEXEC_SRCS += kexec/arch/ppc/kexec-uImage-ppc.c
 ppc_KEXEC_SRCS += kexec/arch/ppc/ppc-setup-simple.S
 ppc_KEXEC_SRCS += kexec/arch/ppc/ppc-setup-dol.S
 ppc_KEXEC_SRCS += kexec/arch/ppc/fixup_dtb.c
-ppc_KEXEC_SRCS += kexec/arch/ppc/fs2dt.c
 ppc_KEXEC_SRCS += kexec/arch/ppc/crashdump-powerpc.c
 
 ppc_UIMAGE = kexec/kexec-uImage.c
diff --git a/kexec/arch/ppc/crashdump-powerpc.c b/kexec/arch/ppc/crashdump-powerpc.c
index 4c8c75d..984079d 100644
--- a/kexec/arch/ppc/crashdump-powerpc.c
+++ b/kexec/arch/ppc/crashdump-powerpc.c
@@ -49,7 +49,7 @@ static int crash_max_memory_ranges;
  * Used to save various memory ranges/regions needed for the captured
  * kernel to boot. (lime memmap= option in other archs)
  */
-mem_rgns_t usablemem_rgns = {0, NULL};
+struct memory_ranges usablemem_rgns = {0, NULL};
 
 /*
  * To store the memory size of the first kernel and this value will be
diff --git a/kexec/arch/ppc/crashdump-powerpc.h b/kexec/arch/ppc/crashdump-powerpc.h
index a377146..4d3b9d9 100644
--- a/kexec/arch/ppc/crashdump-powerpc.h
+++ b/kexec/arch/ppc/crashdump-powerpc.h
@@ -43,4 +43,6 @@ extern unsigned long long crash_size;
 extern unsigned int rtas_base;
 extern unsigned int rtas_size;
 
+extern struct memory_ranges usablemem_rgns;
+
 #endif /* CRASHDUMP_POWERPC_H */
diff --git a/kexec/arch/ppc/fs2dt.c b/kexec/arch/ppc/fs2dt.c
deleted file mode 100644
index cdae69e..0000000
--- a/kexec/arch/ppc/fs2dt.c
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * fs2dt: creates a flattened device-tree
- *
- * Copyright (C) 2004,2005  Milton D Miller II, IBM Corporation
- * Copyright (C) 2005  R Sharada (sharada at in.ibm.com), 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 (version 2 of the License).
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <fcntl.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-#include "../../kexec.h"
-#include "kexec-ppc.h"
-
-#define MAXPATH			1024	/* max path name length */
-#define NAMESPACE		16384	/* max bytes for property names */
-#define TREEWORDS		65536	/* max 32 bit words for properties */
-#define MEMRESERVE		256	/* max number of reserved memory blks */
-#define MAX_MEMORY_RANGES	1024
-#define COMMAND_LINE_SIZE	512	/* from kernel */
-
-static char pathname[MAXPATH];
-static char propnames[NAMESPACE] = { 0 };
-static unsigned dtstruct[TREEWORDS], *dt;
-static unsigned long long mem_rsrv[2*MEMRESERVE] = { 0, 0 };
-
-static int crash_param;
-static char local_cmdline[COMMAND_LINE_SIZE] = { "" };
-static unsigned *dt_len; /* changed len of modified cmdline
-			    in flat device-tree */
-static struct bootblock bb[1];
-
-void reserve(unsigned long long where, unsigned long long length)
-{
-	size_t offset;
-
-	for (offset = 0; mem_rsrv[offset + 1]; offset += 2)
-		;
-
-	if (offset + 4 >= 2 * MEMRESERVE)
-		die("unrecoverable error: exhasuted reservation meta data\n");
-
-	mem_rsrv[offset] = where;
-	mem_rsrv[offset + 1] = length;
-	mem_rsrv[offset + 3] = 0;  /* N.B: don't care about offset + 2 */
-}
-
-/* look for properties we need to reserve memory space for */
-static void checkprop(char *name, unsigned *data, int len)
-{
-	static unsigned long long base, size, end;
-
-	if ((data == NULL) && (base || size || end))
-		die("unrecoverable error: no property data");
-	else if (!strcmp(name, "linux,rtas-base"))
-		base = *data;
-	else if (!strcmp(name, "linux,tce-base"))
-		base = *(unsigned long long *) data;
-	else if (!strcmp(name, "rtas-size") ||
-			!strcmp(name, "linux,tce-size"))
-		size = *data;
-	else if (reuse_initrd && !strcmp(name, "linux,initrd-start"))
-		if (len == 8)
-			base = *(unsigned long long *) data;
-		else
-			base = *data;
-	else if (reuse_initrd && !strcmp(name, "linux,initrd-end"))
-		end = *(unsigned long long *) data;
-
-	if (size && end)
-		die("unrecoverable error: size and end set at same time\n");
-	if (base && size) {
-		reserve(base, size);
-		base = 0;
-		size = 0;
-	}
-	if (base && end) {
-		reserve(base, end-base);
-		base = 0;
-		end = 0;
-	}
-}
-
-/*
- * return the property index for a property name, creating a new one
- * if needed.
- */
-static unsigned propnum(const char *name)
-{
-	unsigned offset = 0;
-
-	while (propnames[offset])
-		if (strcmp(name, propnames+offset))
-			offset += strlen(propnames+offset)+1;
-		else
-			return offset;
-
-	if (NAMESPACE - offset < strlen(name) + 1)
-		die("unrecoverable error: propnames overrun\n");
-
-	strcpy(propnames+offset, name);
-
-	return offset;
-}
-
-static void add_usable_mem_property(int fd, int len)
-{
-	char fname[MAXPATH], *bname;
-	unsigned long buf[2];
-	unsigned long ranges[2*MAX_MEMORY_RANGES];
-	unsigned long long base, end, loc_base, loc_end;
-	int range, rlen = 0;
-
-	strcpy(fname, pathname);
-	bname = strrchr(fname, '/');
-	bname[0] = '\0';
-	bname = strrchr(fname, '/');
-	if (strncmp(bname, "/memory@", 8) && strcmp(bname, "/memory"))
-		return;
-
-	if (lseek(fd, 0, SEEK_SET) < 0)
-		die("unrecoverable error: error seeking in \"%s\": %s\n",
-		    pathname, strerror(errno));
-	if (read_memory_region_limits(fd, &base, &end) != 0)
-		die("unrecoverable error: error parsing memory/reg limits\n");
-
-	for (range = 0; range < usablemem_rgns.size; range++) {
-		loc_base = usablemem_rgns.ranges[range].start;
-		loc_end = usablemem_rgns.ranges[range].end;
-		if (loc_base >= base && loc_end <= end) {
-			ranges[rlen++] = loc_base;
-			ranges[rlen++] = loc_end - loc_base;
-		} else if (base < loc_end && end > loc_base) {
-			if (loc_base < base)
-				loc_base = base;
-			if (loc_end > end)
-				loc_end = end;
-			ranges[rlen++] = loc_base;
-			ranges[rlen++] = loc_end - loc_base;
-		}
-	}
-
-	if (!rlen) {
-		/*
-		 * User did not pass any ranges for thsi region. Hence, write
-		 * (0,0) duple in linux,usable-memory property such that
-		 * this region will be ignored.
-		 */
-		ranges[rlen++] = 0;
-		ranges[rlen++] = 0;
-	}
-
-	rlen = rlen * sizeof(unsigned long);
-	/*
-	 * No add linux,usable-memory property.
-	 */
-	*dt++ = 3;
-	*dt++ = rlen;
-	*dt++ = propnum("linux,usable-memory");
-	memcpy(dt, &ranges, rlen);
-	dt += (rlen + 3)/4;
-}
-
-/* put all properties (files) in the property structure */
-static void putprops(char *fn, struct dirent **nlist, int numlist)
-{
-	struct dirent *dp;
-	int i = 0, fd, len;
-	struct stat statbuf;
-
-	for (i = 0; i < numlist; i++) {
-		dp = nlist[i];
-		strcpy(fn, dp->d_name);
-
-		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
-			continue;
-
-		if (lstat(pathname, &statbuf))
-			die("unrecoverable error: could not stat \"%s\": %s\n",
-			    pathname, strerror(errno));
-
-		if (!crash_param && !strcmp(fn, "linux,crashkernel-base"))
-			continue;
-
-		if (!crash_param && !strcmp(fn, "linux,crashkernel-size"))
-			continue;
-
-		/*
-		 * This property will be created for each node during kexec
-		 * boot. So, ignore it.
-		 */
-		if (!strcmp(dp->d_name, "linux,pci-domain") ||
-			!strcmp(dp->d_name, "linux,htab-base") ||
-			!strcmp(dp->d_name, "linux,htab-size") ||
-			!strcmp(dp->d_name, "linux,kernel-end") ||
-			!strcmp(dp->d_name, "linux,usable-memory"))
-				continue;
-
-		/* This property will be created/modified later in putnode()
-		 * So ignore it, unless we are reusing the initrd.
-		 */
-		if ((!strcmp(dp->d_name, "linux,initrd-start") ||
-		     !strcmp(dp->d_name, "linux,initrd-end")) &&
-		    !reuse_initrd)
-				continue;
-
-		if (!S_ISREG(statbuf.st_mode))
-			continue;
-
-		len = statbuf.st_size;
-
-		*dt++ = 3;
-		dt_len = dt;
-		*dt++ = len;
-		*dt++ = propnum(fn);
-
-		fd = open(pathname, O_RDONLY);
-		if (fd == -1)
-			die("unrecoverable error: could not open \"%s\": %s\n",
-			    pathname, strerror(errno));
-
-		if (read(fd, dt, len) != len)
-			die("unrecoverable error: could not read \"%s\": %s\n",
-			    pathname, strerror(errno));
-
-		checkprop(fn, dt, len);
-
-		/* Get the cmdline from the device-tree and modify it */
-		if (!strcmp(dp->d_name, "bootargs")) {
-			int cmd_len;
-			char temp_cmdline[COMMAND_LINE_SIZE] = { "" };
-			char *param = NULL;
-			cmd_len = strlen(local_cmdline);
-			if (cmd_len != 0) {
-				param = strstr(local_cmdline, "crashkernel=");
-				if (param)
-					crash_param = 1;
-				param = strstr(local_cmdline, "root=");
-			}
-			if (!param) {
-				char *old_param;
-				memcpy(temp_cmdline, dt, len);
-				param = strstr(temp_cmdline, "root=");
-				if (param) {
-					old_param = strtok(param, " ");
-					if (cmd_len != 0)
-						strcat(local_cmdline, " ");
-					strcat(local_cmdline, old_param);
-				}
-			}
-			strcat(local_cmdline, " ");
-			cmd_len = strlen(local_cmdline);
-			cmd_len = cmd_len + 1;
-			memcpy(dt, local_cmdline, cmd_len);
-			len = cmd_len;
-			*dt_len = cmd_len;
-
-			dbgprintf("Modified cmdline:%s\n", local_cmdline);
-
-		}
-
-		dt += (len + 3)/4;
-		if (!strcmp(dp->d_name, "reg") && usablemem_rgns.size)
-			add_usable_mem_property(fd, len);
-		close(fd);
-	}
-
-	fn[0] = '\0';
-	checkprop(pathname, NULL, 0);
-}
-
-/*
- * Compare function used to sort the device-tree directories
- * This function will be passed to scandir.
- */
-static int comparefunc(const void *dentry1, const void *dentry2)
-{
-	char *str1 = (*(struct dirent **)dentry1)->d_name;
-	char *str2 = (*(struct dirent **)dentry2)->d_name;
-
-	/*
-	 * strcmp scans from left to right and fails to idetify for some
-	 * strings such as memory at 10000000 and memory at f000000.
-	 * Therefore, we get the wrong sorted order like memory at 10000000 and
-	 * memory at f000000.
-	 */
-	if (strchr(str1, '@') && strchr(str2, '@') &&
-		(strlen(str1) > strlen(str2)))
-		return 1;
-
-	return strcmp(str1, str2);
-}
-
-/*
- * put a node (directory) in the property structure.  first properties
- * then children.
- */
-static void putnode(void)
-{
-	char *dn;
-	struct dirent *dp;
-	char *basename;
-	struct dirent **namelist;
-	int numlist, i;
-	struct stat statbuf;
-
-	numlist = scandir(pathname, &namelist, 0, comparefunc);
-	if (numlist < 0)
-		die("unrecoverable error: could not scan \"%s\": %s\n",
-		    pathname, strerror(errno));
-	if (numlist == 0)
-		die("unrecoverable error: no directory entries in \"%s\"",
-		    pathname);
-
-	basename = strrchr(pathname, '/') + 1;
-
-	*dt++ = 1;
-	strcpy((void *)dt, *basename ? basename : "");
-	dt += strlen((void *)dt) / sizeof(unsigned) + 1;
-
-	strcat(pathname, "/");
-	dn = pathname + strlen(pathname);
-
-	putprops(dn, namelist, numlist);
-
-	/* Add initrd entries to the second kernel */
-	if (initrd_base && !strcmp(basename, "chosen/")) {
-		int len = 8;
-		unsigned long long initrd_end;
-		*dt++ = 3;
-		*dt++ = len;
-		*dt++ = propnum("linux,initrd-start");
-
-		memcpy(dt, &initrd_base, len);
-		dt += (len + 3)/4;
-
-		len = 8;
-		*dt++ = 3;
-		*dt++ = len;
-		*dt++ = propnum("linux,initrd-end");
-
-		initrd_end = initrd_base + initrd_size;
-
-		memcpy(dt, &initrd_end, len);
-		dt += (len + 3)/4;
-
-		reserve(initrd_base, initrd_size);
-	}
-
-	for (i = 0; i < numlist; i++) {
-		dp = namelist[i];
-		strcpy(dn, dp->d_name);
-		free(namelist[i]);
-
-		if (!strcmp(dn, ".") || !strcmp(dn, ".."))
-			continue;
-
-		if (lstat(pathname, &statbuf))
-			die("unrecoverable error: could not stat \"%s\": %s\n",
-			    pathname, strerror(errno));
-
-		if (S_ISDIR(statbuf.st_mode))
-			putnode();
-	}
-
-	*dt++ = 2;
-	dn[-1] = '\0';
-	free(namelist);
-}
-
-int create_flatten_tree(struct kexec_info *info, unsigned char **bufp,
-			unsigned long *sizep, char *cmdline)
-{
-	unsigned long len;
-	unsigned long tlen;
-	unsigned char *buf;
-	unsigned long me;
-
-	me = 0;
-
-	strcpy(pathname, "/proc/device-tree/");
-
-	dt = dtstruct;
-
-	if (cmdline)
-		strcpy(local_cmdline, cmdline);
-
-	putnode();
-	*dt++ = 9;
-
-	len = sizeof(bb[0]);
-	len += 7; len &= ~7;
-
-	bb->off_mem_rsvmap = len;
-
-	for (len = 1; mem_rsrv[len]; len += 2)
-		;
-	len += 3;
-	len *= sizeof(mem_rsrv[0]);
-
-	bb->off_dt_struct = bb->off_mem_rsvmap + len;
-
-	len = dt - dtstruct;
-	len *= sizeof(unsigned);
-	bb->dt_struct_size = len;
-	bb->off_dt_strings = bb->off_dt_struct + len;
-
-	len = propnum("");
-	bb->dt_strings_size = len;
-	len +=  3; len &= ~3;
-	bb->totalsize = bb->off_dt_strings + len;
-
-	bb->magic = 0xd00dfeed;
-	bb->version = 17;
-	bb->last_comp_version = 16;
-
-	reserve(me, bb->totalsize); /* patched later in kexec_load */
-
-	buf = (unsigned char *) malloc(bb->totalsize);
-	*bufp = buf;
-	memcpy(buf, bb, bb->off_mem_rsvmap);
-	tlen = bb->off_mem_rsvmap;
-	memcpy(buf+tlen, mem_rsrv, bb->off_dt_struct - bb->off_mem_rsvmap);
-	tlen = tlen + (bb->off_dt_struct - bb->off_mem_rsvmap);
-	memcpy(buf+tlen, dtstruct,  bb->off_dt_strings - bb->off_dt_struct);
-	tlen = tlen +  (bb->off_dt_strings - bb->off_dt_struct);
-	memcpy(buf+tlen, propnames,  bb->totalsize - bb->off_dt_strings);
-	tlen = tlen + bb->totalsize - bb->off_dt_strings;
-	*sizep = tlen;
-	return 0;
-}
diff --git a/kexec/arch/ppc/kexec-elf-ppc.c b/kexec/arch/ppc/kexec-elf-ppc.c
index 314eb1e..decf82d 100644
--- a/kexec/arch/ppc/kexec-elf-ppc.c
+++ b/kexec/arch/ppc/kexec-elf-ppc.c
@@ -34,8 +34,6 @@ static const int probe_debug = 0;
 
 unsigned char reuse_initrd;
 const char *ramdisk;
-int create_flatten_tree(struct kexec_info *, unsigned char **, unsigned long *,
-			char *);
 
 #define UPSZ(X) ((sizeof(X) + 3) & ~3)
 #ifdef WITH_GAMECUBE
diff --git a/kexec/arch/ppc/kexec-ppc.h b/kexec/arch/ppc/kexec-ppc.h
index 68728c6..39ebb19 100644
--- a/kexec/arch/ppc/kexec-ppc.h
+++ b/kexec/arch/ppc/kexec-ppc.h
@@ -1,10 +1,17 @@
 #ifndef KEXEC_PPC_H
 #define KEXEC_PPC_H
 
+#include <stdint.h>
+#include <sys/types.h>
+#include "../../kexec.h"
+
 #define MAXBYTES	128
 #define MAX_LINE	160
 #define CORE_TYPE_ELF32	1
 #define CORE_TYPE_ELF64	2
+#define BOOT_BLOCK_VERSION 17
+#define BOOT_BLOCK_LAST_COMP_VERSION 16
+#define NEED_RESERVE_DTB
 
 extern unsigned char setup_simple_start[];
 extern uint32_t setup_simple_size;
@@ -44,25 +51,6 @@ void dol_ppc_usage(void);
  */
 #define KERNEL_ACCESS_TOP (24 * 1024 * 1024)
 
-/* boot block version 17 as defined by the linux kernel */
-struct bootblock {
-	unsigned magic,
-		totalsize,
-		off_dt_struct,
-		off_dt_strings,
-		off_mem_rsvmap,
-		version,
-		last_comp_version,
-		boot_physid,
-		dt_strings_size,
-		dt_struct_size;
-};
-
-typedef struct mem_rgns {
-	unsigned int size;
-	struct memory_range *ranges;
-} mem_rgns_t;
-extern mem_rgns_t usablemem_rgns;
 extern int max_memory_ranges;
 extern unsigned long long crash_base, crash_size;
 extern unsigned long long initrd_base, initrd_size;
diff --git a/kexec/arch/ppc/kexec-uImage-ppc.c b/kexec/arch/ppc/kexec-uImage-ppc.c
index b5579f0..61b4513 100644
--- a/kexec/arch/ppc/kexec-uImage-ppc.c
+++ b/kexec/arch/ppc/kexec-uImage-ppc.c
@@ -17,9 +17,6 @@
 #include "crashdump-powerpc.h"
 #include <limits.h>
 
-int create_flatten_tree(struct kexec_info *, unsigned char **, unsigned long *,
-			char *);
-
 /* See options.h -- add any more there, too. */
 static const struct option options[] = {
 	KEXEC_ARCH_OPTIONS
-- 
1.7.12



From matthew.leach at arm.com  Fri Sep  7 05:11:25 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Fri,  7 Sep 2012 10:11:25 +0100
Subject: [PATCH 6/7] arm: Make use of memory_ranges
In-Reply-To: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
References: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
Message-ID: <1347009086-16506-7-git-send-email-matthew.leach@arm.com>

From: Simon Horman <horms at verge.net.au>

Make use of struct memory_ranges and provide a global usablemem_rgns.
This is in preparation for adding device tree support.

Signed-off-by: Simon Horman <horms at verge.net.au>
---
 kexec/arch/arm/crashdump-arm.c | 45 ++++++++++++++++++++++++++----------------
 kexec/arch/arm/crashdump-arm.h |  2 ++
 2 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c
index 213dae2..01973b1 100644
--- a/kexec/arch/arm/crashdump-arm.c
+++ b/kexec/arch/arm/crashdump-arm.c
@@ -31,8 +31,16 @@
 #include "../../crashdump.h"
 #include "crashdump-arm.h"
 
+
+/*
+ * Used to save various memory ranges/regions needed for the captured
+ * kernel to boot. (lime memmap= option in other archs)
+ */
 static struct memory_range crash_memory_ranges[CRASH_MAX_MEMORY_RANGES];
-static int crash_memory_nr_ranges;
+struct memory_ranges usablemem_rgns = {
+    .size = 0,
+    .ranges = crash_memory_ranges,
+};
 
 /* memory range reserved for crashkernel */
 static struct memory_range crash_reserved_mem;
@@ -65,16 +73,16 @@ static int crash_range_callback(void *UNUSED(data), int UNUSED(nr),
 {
 	struct memory_range *range;
 
-	if (crash_memory_nr_ranges >= CRASH_MAX_MEMORY_RANGES)
+	if (usablemem_rgns.size >= CRASH_MAX_MEMORY_RANGES)
 		return 1;
 
-	range = &crash_memory_ranges[crash_memory_nr_ranges];
+	range = usablemem_rgns.ranges + usablemem_rgns.size;
 
 	if (strncmp(str, "System RAM\n", 11) == 0) {
 		range->start = base;
 		range->end = base + length - 1;
 		range->type = RANGE_RAM;
-		crash_memory_nr_ranges++;
+		usablemem_rgns.size++;
 	} else if (strncmp(str, "Crash kernel\n", 13) == 0) {
 		crash_reserved_mem.start = base;
 		crash_reserved_mem.end = base + length - 1;
@@ -95,22 +103,24 @@ static void crash_exclude_range(void)
 	const struct memory_range *range = &crash_reserved_mem;
 	int i;
 
-	for (i = 0; i < crash_memory_nr_ranges; i++) {
-		struct memory_range *r = &crash_memory_ranges[i];
+	for (i = 0; i < usablemem_rgns.size; i++) {
+		struct memory_range *r = usablemem_rgns.ranges + i;
 
 		/*
 		 * We assume that crash area is fully contained in
 		 * some larger memory area.
 		 */
 		if (r->start <= range->start && r->end >= range->end) {
+			struct memory_range *new;
 			/*
 			 * Let's split this area into 2 smaller ones and
 			 * remove excluded range from between. First create
 			 * new entry for the remaining area.
 			 */
-			crash_memory_ranges[crash_memory_nr_ranges].start = range->end + 1;
-			crash_memory_ranges[crash_memory_nr_ranges].end = r->end;
-			crash_memory_nr_ranges++;
+			new = usablemem_rgns.ranges + usablemem_rgns.size;
+			new->start = range->end + 1;
+			new->end = r->end;
+			usablemem_rgns.size++;
 			/*
 			 * Next update this area to end before excluded range.
 			 */
@@ -150,7 +160,7 @@ static int crash_get_memory_ranges(void)
 	 */
 	kexec_iomem_for_each_line(NULL, crash_range_callback, NULL);
 
-	if (crash_memory_nr_ranges < 1) {
+	if (usablemem_rgns.size < 1) {
 		errno = EINVAL;
 		return -1;
 	}
@@ -164,8 +174,8 @@ static int crash_get_memory_ranges(void)
 	/*
 	 * Make sure that the memory regions are sorted.
 	 */
-	qsort(crash_memory_ranges, crash_memory_nr_ranges,
-	      sizeof(crash_memory_ranges[0]), range_cmp);
+	qsort(usablemem_rgns.ranges, usablemem_rgns.size,
+	      sizeof(*usablemem_rgns.ranges), range_cmp);
 
 	return 0;
 }
@@ -235,8 +245,8 @@ static void dump_memory_ranges(void)
 		  crash_reserved_mem.start, crash_reserved_mem.end,
 		  (unsigned long)range_size(&crash_reserved_mem) >> 20);
 
-	for (i = 0; i < crash_memory_nr_ranges; i++) {
-		struct memory_range *r = &crash_memory_ranges[i];
+	for (i = 0; i < usablemem_rgns.size; i++) {
+		struct memory_range *r = usablemem_rgns.ranges + i;
 		dbgprintf("memory range: [%#llx - %#llx] (%ldM)\n",
 			  r->start, r->end, (unsigned long)range_size(r) >> 20);
 	}
@@ -272,11 +282,12 @@ int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline)
 	 * Now that we have memory regions sorted, we can use first memory
 	 * region as PHYS_OFFSET.
 	 */
-	phys_offset = crash_memory_ranges[0].start;
+	phys_offset = usablemem_rgns.ranges->start;
 	dbgprintf("phys_offset: %#lx\n", phys_offset);
 
-	err = crash_create_elf32_headers(info, &elf_info, crash_memory_ranges,
-					 crash_memory_nr_ranges, &buf, &bufsz,
+	err = crash_create_elf32_headers(info, &elf_info,
+					 usablemem_rgns.ranges,
+					 usablemem_rgns.size, &buf, &bufsz,
 					 ELF_CORE_HEADER_ALIGN);
 	if (err)
 		return err;
diff --git a/kexec/arch/arm/crashdump-arm.h b/kexec/arch/arm/crashdump-arm.h
index a2e7824..a342922 100644
--- a/kexec/arch/arm/crashdump-arm.h
+++ b/kexec/arch/arm/crashdump-arm.h
@@ -9,6 +9,8 @@ extern "C" {
 #define PAGE_OFFSET		0xc0000000
 #define CRASH_MAX_MEMORY_RANGES	32
 
+extern struct memory_ranges usablemem_rgns;
+
 struct kexec_info;
 
 extern unsigned long phys_offset;
-- 
1.7.12



From matthew.leach at arm.com  Fri Sep  7 05:11:23 2012
From: matthew.leach at arm.com (Matthew Leach)
Date: Fri,  7 Sep 2012 10:11:23 +0100
Subject: [PATCH 4/7] ppc64: Move 64bit powerpc to use generic fs2dt code
In-Reply-To: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
References: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
Message-ID: <1347009086-16506-5-git-send-email-matthew.leach@arm.com>

From: Simon Horman <horms at verge.net.au>

Compile tested only

Signed-off-by: Simon Horman <horms at verge.net.au>
---
 kexec/arch/ppc64/Makefile          |   7 +-
 kexec/arch/ppc64/crashdump-ppc64.c |   3 +-
 kexec/arch/ppc64/crashdump-ppc64.h |   4 +
 kexec/arch/ppc64/fs2dt.c           | 744 -------------------------------------
 kexec/arch/ppc64/kexec-elf-ppc64.c |   4 +-
 kexec/arch/ppc64/kexec-ppc64.c     |   1 +
 kexec/arch/ppc64/kexec-ppc64.h     |  29 +-
 7 files changed, 23 insertions(+), 769 deletions(-)
 delete mode 100644 kexec/arch/ppc64/fs2dt.c

diff --git a/kexec/arch/ppc64/Makefile b/kexec/arch/ppc64/Makefile
index 7ed0aa9..311c6c4 100644
--- a/kexec/arch/ppc64/Makefile
+++ b/kexec/arch/ppc64/Makefile
@@ -1,9 +1,14 @@
 #
 # kexec ppc64 (linux booting linux)
 #
+include $(srcdir)/kexec/libfdt/Makefile.libfdt
+
+ppc64_FS2DT		= kexec/fs2dt.c
+ppc64_FS2DT_INCLUDE	= -include kexec/arch/ppc64/crashdump-ppc64.h \
+			  -include kexec/arch/ppc64/kexec-ppc64.h
+
 ppc64_KEXEC_SRCS =  kexec/arch/ppc64/kexec-elf-rel-ppc64.c
 ppc64_KEXEC_SRCS += kexec/arch/ppc64/kexec-zImage-ppc64.c
-ppc64_KEXEC_SRCS += kexec/arch/ppc64/fs2dt.c
 ppc64_KEXEC_SRCS += kexec/arch/ppc64/kexec-elf-ppc64.c
 ppc64_KEXEC_SRCS += kexec/arch/ppc64/kexec-ppc64.c
 ppc64_KEXEC_SRCS += kexec/arch/ppc64/crashdump-ppc64.c
diff --git a/kexec/arch/ppc64/crashdump-ppc64.c b/kexec/arch/ppc64/crashdump-ppc64.c
index 30ef443..5c78592 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.c
+++ b/kexec/arch/ppc64/crashdump-ppc64.c
@@ -33,6 +33,7 @@
 #include "../../kexec-syscall.h"
 #include "../../crashdump.h"
 #include "kexec-ppc64.h"
+#include "../../fs2dt.h"
 #include "crashdump-ppc64.h"
 
 static struct crash_elf_info elf_info64 =
@@ -67,7 +68,7 @@ static int crash_max_memory_ranges;
  * Used to save various memory ranges/regions needed for the captured
  * kernel to boot. (lime memmap= option in other archs)
  */
-mem_rgns_t usablemem_rgns = {0, NULL};
+struct memory_ranges usablemem_rgns = {0, NULL};
 
 /*
  * To store the memory size of the first kernel and this value will be
diff --git a/kexec/arch/ppc64/crashdump-ppc64.h b/kexec/arch/ppc64/crashdump-ppc64.h
index be02213..1a5b5f3 100644
--- a/kexec/arch/ppc64/crashdump-ppc64.h
+++ b/kexec/arch/ppc64/crashdump-ppc64.h
@@ -1,6 +1,9 @@
 #ifndef CRASHDUMP_PPC64_H
 #define CRASHDUMP_PPC64_H
 
+#include <stdint.h>
+#include "../../kexec.h"
+
 struct kexec_info;
 int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline,
 				uint64_t max_addr, unsigned long min_base);
@@ -29,6 +32,7 @@ extern uint64_t crash_base;
 extern uint64_t crash_size;
 extern unsigned int rtas_base;
 extern unsigned int rtas_size;
+extern struct memory_ranges usablemem_rgns;
 
 uint64_t lmb_size;
 unsigned int num_of_lmbs;
diff --git a/kexec/arch/ppc64/fs2dt.c b/kexec/arch/ppc64/fs2dt.c
deleted file mode 100644
index d2b6b18..0000000
--- a/kexec/arch/ppc64/fs2dt.c
+++ /dev/null
@@ -1,744 +0,0 @@
-/*
- * fs2dt: creates a flattened device-tree
- *
- * Copyright (C) 2004,2005  Milton D Miller II, IBM Corporation
- * Copyright (C) 2005  R Sharada (sharada at in.ibm.com), 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 (version 2 of the License).
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#define _GNU_SOURCE
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <fcntl.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-#include "../../kexec.h"
-#include "kexec-ppc64.h"
-#include "crashdump-ppc64.h"
-
-#define MAXPATH 1024		/* max path name length */
-#define NAMESPACE 16384		/* max bytes for property names */
-#define INIT_TREE_WORDS 65536	/* Initial num words for prop values */
-#define MEMRESERVE 256		/* max number of reserved memory blocks */
-#define MEM_RANGE_CHUNK_SZ 2048 /* Initial num dwords for mem ranges */
-
-static char pathname[MAXPATH], *pathstart;
-static char propnames[NAMESPACE] = { 0 };
-static unsigned *dt_base, *dt;
-static unsigned int dt_cur_size;
-static unsigned long long mem_rsrv[2*MEMRESERVE] = { 0, 0 };
-
-static int crash_param = 0;
-static char local_cmdline[COMMAND_LINE_SIZE] = { "" };
-extern mem_rgns_t usablemem_rgns;
-static struct bootblock bb[1];
-extern int my_debug;
-
-/* Before we add something to the dt, reserve N words using this.
- * If there isn't enough room, it's realloced -- and you don't overflow and
- * splat bits of your heap. 
- */
-void dt_reserve(unsigned **dt_ptr, unsigned words)
-{
-	unsigned int sz = INIT_TREE_WORDS;
-
-	if (sz < words)
-		sz = words;
-
-	if (((*dt_ptr - dt_base) + words) >= dt_cur_size) {
-		int offset;
-		unsigned int new_size = dt_cur_size + sz;
-		unsigned *new_dt = realloc(dt_base, new_size*4);
-
-		if (!new_dt)
-			die("unrecoverable error: Can't realloc %d bytes for "
-			    "device tree\n", new_size*4);
-		offset = *dt_ptr - dt_base;
-		dt_base = new_dt;
-		dt_cur_size = new_size;
-		*dt_ptr = dt_base + offset;
-		memset(*dt_ptr, 0, (new_size - offset)*4);
-	}
-}
-
-void reserve(unsigned long long where, unsigned long long length)
-{
-	size_t offset;
-
-	for (offset = 0; mem_rsrv[offset + 1]; offset += 2)
-		;
-
-	if (offset + 4 >= 2 * MEMRESERVE)
-		die("unrecoverable error: exhasuted reservation meta data\n");
-
-	mem_rsrv[offset] = where;
-	mem_rsrv[offset + 1] = length;
-	mem_rsrv[offset + 3] = 0;  /* N.B: don't care about offset + 2 */
-}
-
-/* look for properties we need to reserve memory space for */
-static void checkprop(char *name, unsigned *data, int len)
-{
-	static unsigned long long base, size, end;
-
-	if ((data == NULL) && (base || size || end))
-		die("unrecoverable error: no property data");
-	else if (!strcmp(name, "linux,rtas-base"))
-		base = *data;
-	else if (!strcmp(name, "linux,tce-base"))
-		base = *(unsigned long long *) data;
-	else if (!strcmp(name, "rtas-size") ||
-			!strcmp(name, "linux,tce-size"))
-		size = *data;
-	else if (reuse_initrd && !strcmp(name, "linux,initrd-start"))
-		if (len == 8)
-			base = *(unsigned long long *) data;
-		else
-			base = *data;
-	else if (reuse_initrd && !strcmp(name, "linux,initrd-end"))
-		end = *(unsigned long long *) data;
-
-	if (size && end)
-		die("unrecoverable error: size and end set at same time\n");
-	if (base && size) {
-		reserve(base, size);
-		base = size = 0;
-	}
-	if (base && end) {
-		reserve(base, end-base);
-		base = end = 0;
-	}
-}
-
-/*
- * return the property index for a property name, creating a new one
- * if needed.
- */
-static unsigned propnum(const char *name)
-{
-	unsigned offset = 0;
-
-	while(propnames[offset])
-		if (strcmp(name, propnames+offset))
-			offset += strlen(propnames+offset)+1;
-		else
-			return offset;
-
-	if (NAMESPACE - offset < strlen(name) + 1)
-		die("unrecoverable error: propnames overrun\n");
-
-	strcpy(propnames+offset, name);
-
-	return offset;
-}
-
-static void add_dyn_reconf_usable_mem_property(int fd)
-{
-	char fname[MAXPATH], *bname;
-	uint64_t buf[32];
-	uint64_t *ranges;
-	int ranges_size = MEM_RANGE_CHUNK_SZ;
-	uint64_t base, end, loc_base, loc_end;
-	size_t i, rngs_cnt, range;
-	int rlen = 0;
-	int tmp_indx;
-
-	strcpy(fname, pathname);
-	bname = strrchr(fname, '/');
-	bname[0] = '\0';
-	bname = strrchr(fname, '/');
-	if (strncmp(bname, "/ibm,dynamic-reconfiguration-memory", 36))
-		return;
-
-	if (lseek(fd, 4, SEEK_SET) < 0)
-		die("unrecoverable error: error seeking in \"%s\": %s\n",
-			pathname, strerror(errno));
-
-	ranges = malloc(ranges_size*8);
-	if (!ranges)
-		die("unrecoverable error: can't alloc %d bytes for ranges.\n",
-		    ranges_size*8);
-
-	rlen = 0;
-	for (i = 0; i < num_of_lmbs; i++) {
-		if (read(fd, buf, 24) < 0)
-			die("unrecoverable error: error reading \"%s\": %s\n",
-				pathname, strerror(errno));
-
-		base = (uint64_t) buf[0];
-		end = base + lmb_size;
-		if (~0ULL - base < end)
-			die("unrecoverable error: mem property overflow\n");
-
-		tmp_indx = rlen++;
-
-		rngs_cnt = 0;
-		for (range = 0; range < usablemem_rgns.size; range++) {
-			int add = 0;
-			loc_base = usablemem_rgns.ranges[range].start;
-			loc_end = usablemem_rgns.ranges[range].end;
-			if (loc_base >= base && loc_end <= end) {
-				add = 1;
-			} else if (base < loc_end && end > loc_base) {
-				if (loc_base < base)
-					loc_base = base;
-				if (loc_end > end)
-					loc_end = end;
-				add = 1;
-			}
-
-			if (add) {
-				if (rlen >= (ranges_size-2)) {
-					ranges_size += MEM_RANGE_CHUNK_SZ;
-					ranges = realloc(ranges, ranges_size*8);
-					if (!ranges)
-						die("unrecoverable error: can't"
-						    " realloc %d bytes for"
-						    " ranges.\n",
-						    ranges_size*8);
-				}
-				ranges[rlen++] = loc_base;
-				ranges[rlen++] = loc_end - loc_base;
-				rngs_cnt++;
-			}
-		}
-		if (rngs_cnt == 0) {
-			/* We still need to add a counter for every LMB because
-			 * the kernel parsing code is dumb.  We just have
-			 * a zero in this case, with no following base/len.
-			 */
-			ranges[tmp_indx] = 0;
-			/* rlen is already just tmp_indx+1 as we didn't write
-			 * anything.  Check array size here, as we'll probably
-			 * go on for a while writing zeros now.
-			 */
-			if (rlen >= (ranges_size-1)) {
-				ranges_size += MEM_RANGE_CHUNK_SZ;
-				ranges = realloc(ranges, ranges_size*8);
-				if (!ranges)
-					die("unrecoverable error: can't"
-					    " realloc %d bytes for"
-					    " ranges.\n",
-					    ranges_size*8);
-			}
-		} else {
-			/* Store the count of (base, size) duple */
-			ranges[tmp_indx] = rngs_cnt;
-		}
-	}
-		
-	rlen = rlen * sizeof(uint64_t);
-	/*
-	 * Add linux,drconf-usable-memory property.
-	 */
-	dt_reserve(&dt, 4+((rlen + 3)/4));
-	*dt++ = 3;
-	*dt++ = rlen;
-	*dt++ = propnum("linux,drconf-usable-memory");
-	if ((rlen >= 8) && ((unsigned long)dt & 0x4))
-		dt++;
-	memcpy(dt, ranges, rlen);
-	free(ranges);
-	dt += (rlen + 3)/4;
-}
-
-static void add_usable_mem_property(int fd, size_t len)
-{
-	char fname[MAXPATH], *bname;
-	uint64_t buf[2];
-	uint64_t *ranges;
-	int ranges_size = MEM_RANGE_CHUNK_SZ;
-	uint64_t base, end, loc_base, loc_end;
-	size_t range;
-	int rlen = 0;
-	ssize_t slen;
-
-	strcpy(fname, pathname);
-	bname = strrchr(fname,'/');
-	bname[0] = '\0';
-	bname = strrchr(fname,'/');
-	if (strncmp(bname, "/memory@", 8))
-		return;
-
-	if (len < 2 * sizeof(uint64_t))
-		die("unrecoverable error: not enough data for mem property\n");
-	slen = 2 * sizeof(uint64_t);
-
-	if (lseek(fd, 0, SEEK_SET) < 0)
-		die("unrecoverable error: error seeking in \"%s\": %s\n",
-		    pathname, strerror(errno));
-	if (read(fd, buf, slen) != slen)
-		die("unrecoverable error: error reading \"%s\": %s\n",
-		    pathname, strerror(errno));
-
-	if (~0ULL - buf[0] < buf[1])
-		die("unrecoverable error: mem property overflow\n");
-	base = buf[0];
-	end = base + buf[1];
-
-	ranges = malloc(ranges_size*8);
-	if (!ranges)
-		die("unrecoverable error: can't alloc %d bytes for ranges.\n",
-		    ranges_size*8);
-
-	for (range = 0; range < usablemem_rgns.size; range++) {
-		int add = 0;
-		loc_base = usablemem_rgns.ranges[range].start;
-		loc_end = usablemem_rgns.ranges[range].end;
-		if (loc_base >= base && loc_end <= end) {
-			add = 1;
-		} else if (base < loc_end && end > loc_base) {
-			if (loc_base < base)
-				loc_base = base;
-			if (loc_end > end)
-				loc_end = end;
-			add = 1;
-		}
-		if (add) {
-			if (rlen >= (ranges_size-2)) {
-				ranges_size += MEM_RANGE_CHUNK_SZ;
-				ranges = realloc(ranges, ranges_size*8);
-				if (!ranges)
-					die("unrecoverable error: can't realloc"
-					    "%d bytes for ranges.\n",
-					    ranges_size*8);
-			}
-			ranges[rlen++] = loc_base;
-			ranges[rlen++] = loc_end - loc_base;
-		}
-	}
-
-	if (!rlen) {
-		/*
-		 * User did not pass any ranges for thsi region. Hence, write
-		 * (0,0) duple in linux,usable-memory property such that
-		 * this region will be ignored.
-		 */
-		ranges[rlen++] = 0;
-		ranges[rlen++] = 0;
-	}
-
-	rlen = rlen * sizeof(uint64_t);
-	/*
-	 * No add linux,usable-memory property.
-	 */
-	dt_reserve(&dt, 4+((rlen + 3)/4));
-	*dt++ = 3;
-	*dt++ = rlen;
-	*dt++ = propnum("linux,usable-memory");
-	if ((rlen >= 8) && ((unsigned long)dt & 0x4))
-		dt++;
-	memcpy(dt, ranges, rlen);
-	free(ranges);
-	dt += (rlen + 3)/4;
-}
-
-/* put all properties (files) in the property structure */
-static void putprops(char *fn, struct dirent **nlist, int numlist)
-{
-	struct dirent *dp;
-	int i = 0, fd;
-	size_t len;
-	ssize_t slen;
-	struct stat statbuf;
-
-	for (i = 0; i < numlist; i++) {
-		dp = nlist[i];
-		strcpy(fn, dp->d_name);
-
-		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
-                        continue;
-
-		if (lstat(pathname, &statbuf))
-			die("unrecoverable error: could not stat \"%s\": %s\n",
-			    pathname, strerror(errno));
-
-		if (!crash_param && !strcmp(fn,"linux,crashkernel-base"))
-			continue;
-
-		if (!crash_param && !strcmp(fn,"linux,crashkernel-size"))
-			continue;
-
-		/*
-		 * This property will be created for each node during kexec
-		 * boot. So, ignore it.
-		 */
-		if (!strcmp(dp->d_name, "linux,pci-domain") ||
-			!strcmp(dp->d_name, "linux,htab-base") ||
-			!strcmp(dp->d_name, "linux,htab-size") ||
-			!strcmp(dp->d_name, "linux,kernel-end"))
-				continue;
-
-		/* This property will be created/modified later in putnode()
-		 * So ignore it, unless we are reusing the initrd.
-		 */
-		if ((!strcmp(dp->d_name, "linux,initrd-start") ||
-		     !strcmp(dp->d_name, "linux,initrd-end")) &&
-		    !reuse_initrd)
-				continue;
-
-		/* This property will be created later in putnode() So
-		 * ignore it now.
-		 */
-		if (!strcmp(dp->d_name, "bootargs"))
-			continue;
-
-		if (! S_ISREG(statbuf.st_mode))
-			continue;
-
-		len = statbuf.st_size;
-
-		dt_reserve(&dt, 4+((len + 3)/4));
-		*dt++ = 3;
-		*dt++ = len;
-		*dt++ = propnum(fn);
-
-		if ((len >= 8) && ((unsigned long)dt & 0x4))
-			dt++;
-
-		fd = open(pathname, O_RDONLY);
-		if (fd == -1)
-			die("unrecoverable error: could not open \"%s\": %s\n",
-			    pathname, strerror(errno));
-
-		slen = read(fd, dt, len);
-		if (slen < 0)
-			die("unrecoverable error: could not read \"%s\": %s\n",
-			    pathname, strerror(errno));
-		if ((size_t)slen != len)
-			die("unrecoverable error: short read from\"%s\"\n",
-			    pathname);
-
-		checkprop(fn, dt, len);
-
-		dt += (len + 3)/4;
-		if (!strcmp(dp->d_name, "reg") && usablemem_rgns.size)
-			add_usable_mem_property(fd, len);
-		if (!strcmp(dp->d_name, "ibm,dynamic-memory") &&
-					usablemem_rgns.size)
-			add_dyn_reconf_usable_mem_property(fd);
-
-		close(fd);
-	}
-
-	fn[0] = '\0';
-	checkprop(pathname, NULL, 0);
-}
-
-/*
- * Compare function used to sort the device-tree directories
- * This function will be passed to scandir.
- */
-static int comparefunc(const struct dirent **dentry1,
-		       const struct dirent **dentry2)
-{
-	char *str1 = (*(struct dirent **)dentry1)->d_name;
-	char *str2 = (*(struct dirent **)dentry2)->d_name;
-
-	/*
-	 * strcmp scans from left to right and fails to idetify for some
-	 * strings such as memory at 10000000 and memory at f000000.
-	 * Therefore, we get the wrong sorted order like memory at 10000000 and
-	 * memory at f000000.
-	 */
-	if (strchr(str1, '@') && strchr(str2, '@') &&
-		(strlen(str1) > strlen(str2)))
-		return 1;
-
-	return strcmp(str1, str2);
-}
-
-/*
- * put a node (directory) in the property structure.  first properties
- * then children.
- */
-static void putnode(void)
-{
-	char *dn;
-	struct dirent *dp;
-	char *basename;
-	struct dirent **namelist;
-	int numlist, i;
-	struct stat statbuf;
-	int plen;
-
-	plen = *pathstart ? strlen(pathstart) : 1;
-	/* Reserve space for string packed to words; e.g. string length 10 
-	 * occupies 3 words, length 12 occupies 4 (for terminating \0s).  
-	 * So round up & include the \0:
-	 */
-	dt_reserve(&dt, 1+((plen + 4)/4));
-	*dt++ = 1;
-	strcpy((void *)dt, *pathstart ? pathstart : "/");
-	dt += ((plen + 4)/4);
-
-	numlist = scandir(pathname, &namelist, 0, comparefunc);
-	if (numlist < 0)
-		die("unrecoverable error: could not scan \"%s\": %s\n",
-		    pathname, strerror(errno));
-	if (numlist == 0)
-		die("unrecoverable error: no directory entries in \"%s\"",
-		    pathname);
-
-	basename = strrchr(pathname,'/');
-
-	strcat(pathname, "/");
-	dn = pathname + strlen(pathname);
-
-	putprops(dn, namelist, numlist);
-
-	/* Add initrd entries to the second kernel */
-	if (initrd_base && !strcmp(basename,"/chosen/")) {
-		int len = 8;
-		unsigned long long initrd_end;
-
-		dt_reserve(&dt, 12); /* both props, of 6 words ea. */
-		*dt++ = 3;
-		*dt++ = len;
-		*dt++ = propnum("linux,initrd-start");
-
-		if ((len >= 8) && ((unsigned long)dt & 0x4))
-			dt++;
-
-		memcpy(dt,&initrd_base,len);
-		dt += (len + 3)/4;
-
-		len = 8;
-		*dt++ = 3;
-		*dt++ = len;
-		*dt++ = propnum("linux,initrd-end");
-
-		initrd_end = initrd_base + initrd_size;
-		if ((len >= 8) && ((unsigned long)dt & 0x4))
-			dt++;
-
-		memcpy(dt,&initrd_end,len);
-		dt += (len + 3)/4;
-
-		reserve(initrd_base, initrd_size);
-	}
-
-	/* Add cmdline to the second kernel.  Check to see if the new
-	 * cmdline has a root=.  If not, use the old root= cmdline.  */
-	if (!strcmp(basename,"/chosen/")) {
-		size_t cmd_len = 0;
-		char *param = NULL;
-		char filename[MAXPATH];
-		char *buff;
-		int fd;
-
-		cmd_len = strlen(local_cmdline);
-		if (cmd_len != 0) {
-			param = strstr(local_cmdline, "crashkernel=");
-			if (param)
-				crash_param = 1;
-			/* does the new cmdline have a root= ? ... */
-			param = strstr(local_cmdline, "root=");
-		}
-
-		/* ... if not, grab root= from the old command line */
-		if (!param) {
-			FILE *fp;
-			char *last_cmdline = NULL;
-			char *old_param;
-
-			strcpy(filename, pathname);
-			strcat(filename, "bootargs");
-			fp = fopen(filename, "r");
-			if (fp) {
-				if (getline(&last_cmdline, &cmd_len, fp) == -1)
-					die("unable to read %s\n", filename);
-
-				param = strstr(last_cmdline, "root=");
-				if (param) {
-					old_param = strtok(param, " ");
-					if (cmd_len != 0)
-						strcat(local_cmdline, " ");
-					strcat(local_cmdline, old_param);
-				}
-			}
-			if (last_cmdline)
-				free(last_cmdline);
-		}
-		strcat(local_cmdline, " ");
-		cmd_len = strlen(local_cmdline);
-		cmd_len = cmd_len + 1;
-
-		/* add new bootargs */
-		dt_reserve(&dt, 4+((cmd_len+3)/4));
-		*dt++ = 3;
-		*dt++ = cmd_len;
-		*dt++ = propnum("bootargs");
-		if ((cmd_len >= 8) && ((unsigned long)dt & 0x4))
-			dt++;
-		memcpy(dt, local_cmdline,cmd_len);
-		dt += (cmd_len + 3)/4;
-
-		fprintf(stderr, "Modified cmdline:%s\n", local_cmdline);
-
-		/*
-		 * Determine the platform type/stdout type, so that purgatory
-		 * code can print 'I'm in purgatory' message. Currently only
-		 * pseries/hvcterminal is supported.
-		 */
-		strcpy(filename, pathname);
-		strncat(filename, "linux,stdout-path", MAXPATH);
-		fd = open(filename, O_RDONLY);
-		if (fd == -1) {
-			printf("Unable to find %s, printing from purgatory is diabled\n",
-														filename);
-			goto no_debug;
-		}
-		if (fstat(fd, &statbuf)) {
-			printf("Unable to stat %s, printing from purgatory is diabled\n",
-														filename);
-			close(fd);
-			goto no_debug;
-
-		}
-
-		buff = malloc(statbuf.st_size);
-		if (!buff) {
-			printf("Can not allocate memory for buff\n");
-			close(fd);
-			goto no_debug;
-		}
-		read(fd, buff, statbuf.st_size);
-		close(fd);
-		strncpy(filename, "/proc/device-tree/", MAXPATH);
-		strncat(filename, buff, MAXPATH);
-		strncat(filename, "/compatible", MAXPATH);
-		fd = open(filename, O_RDONLY);
-		if (fd == -1) {
-			printf("Unable to find %s printing from purgatory is diabled\n",
-														filename);
-			goto no_debug;
-		}
-		if (fstat(fd, &statbuf)) {
-			printf("Unable to stat %s printing from purgatory is diabled\n",
-														filename);
-			close(fd);
-			goto no_debug;
-		}
-		buff = realloc(buff, statbuf.st_size);
-		if (!buff) {
-			printf("Can not allocate memory for buff\n");
-			close(fd);
-			goto no_debug;
-		}
-		read(fd, buff, statbuf.st_size);
-		if (!strcmp(buff, "hvterm1") || !strcmp(buff, "hvterm-protocol"))
-			my_debug = 1;
-		close(fd);
-		free(buff);
-	}
-
-no_debug:
-	for (i=0; i < numlist; i++) {
-		dp = namelist[i];
-		strcpy(dn, dp->d_name);
-		free(namelist[i]);
-
-		if (!strcmp(dn, ".") || !strcmp(dn, ".."))
-			continue;
-
-		if (lstat(pathname, &statbuf))
-			die("unrecoverable error: could not stat \"%s\": %s\n",
-			    pathname, strerror(errno));
-
-		if (S_ISDIR(statbuf.st_mode))
-			putnode();
-	}
-
-	dt_reserve(&dt, 1);
-	*dt++ = 2;
-	dn[-1] = '\0';
-	free(namelist);
-}
-
-int create_flatten_tree(char **bufp, off_t *sizep, char *cmdline)
-{
-	unsigned long len;
-	unsigned long tlen;
-	char *buf;
-	unsigned long me;
-
-	me = 0;
-
-	strcpy(pathname, "/proc/device-tree/");
-
-	pathstart = pathname + strlen(pathname);
-
-	dt_cur_size = INIT_TREE_WORDS;
-	dt_base = malloc(dt_cur_size*4);
-	if (!dt_base) {
-		die("Can't malloc %d bytes for dt struct!\n", dt_cur_size*4);
-	}
-	memset(dt_base, 0, dt_cur_size*4);
-
-	dt = dt_base;
-
-	if (cmdline)
-		strcpy(local_cmdline, cmdline);
-
-	putnode();
-	dt_reserve(&dt, 1);
-	*dt++ = 9;
-
-	len = sizeof(bb[0]);
-	len += 7; len &= ~7;
-
-	bb->off_mem_rsvmap = len;
-
-	for (len = 1; mem_rsrv[len]; len += 2)
-		;
-	len+= 3;
-	len *= sizeof(mem_rsrv[0]);
-
-	bb->off_dt_struct = bb->off_mem_rsvmap + len;
-
-	len = dt - dt_base;
-	len *= sizeof(unsigned);
-	bb->off_dt_strings = bb->off_dt_struct + len;
-
-	len = propnum("");
-	len +=  3; len &= ~3;
-	bb->totalsize = bb->off_dt_strings + len;
-
-	bb->magic = 0xd00dfeed;
-	bb->version = 2;
-	bb->last_comp_version = 2;
-
-	reserve(me, bb->totalsize); /* patched later in kexec_load */
-
-	buf = malloc(bb->totalsize);
-	*bufp = buf;
-	memcpy(buf, bb, bb->off_mem_rsvmap);
-	tlen = bb->off_mem_rsvmap;
-	memcpy(buf+tlen, mem_rsrv, bb->off_dt_struct - bb->off_mem_rsvmap);
-	tlen = tlen + (bb->off_dt_struct - bb->off_mem_rsvmap);
-	memcpy(buf+tlen, dt_base,  bb->off_dt_strings - bb->off_dt_struct);
-	tlen = tlen +  (bb->off_dt_strings - bb->off_dt_struct);
-	memcpy(buf+tlen, propnames,  bb->totalsize - bb->off_dt_strings);
-	tlen = tlen + bb->totalsize - bb->off_dt_strings;
-	*sizep = tlen;
-	free(dt_base);
-	return 0;
-}
diff --git a/kexec/arch/ppc64/kexec-elf-ppc64.c b/kexec/arch/ppc64/kexec-elf-ppc64.c
index f68f2bc..26b2f8e 100644
--- a/kexec/arch/ppc64/kexec-elf-ppc64.c
+++ b/kexec/arch/ppc64/kexec-elf-ppc64.c
@@ -35,14 +35,14 @@
 #include "../../kexec-elf.h"
 #include "../../kexec-syscall.h"
 #include "kexec-ppc64.h"
+#include "../../fs2dt.h"
 #include "crashdump-ppc64.h"
 #include <arch/options.h>
 
 uint64_t initrd_base, initrd_size;
 unsigned char reuse_initrd = 0;
 const char *ramdisk;
-/* Used for enabling printing message from purgatory code */
-int my_debug = 0;
+extern int my_debug;
 
 int elf_ppc64_probe(const char *buf, off_t len)
 {
diff --git a/kexec/arch/ppc64/kexec-ppc64.c b/kexec/arch/ppc64/kexec-ppc64.c
index 2f12907..4be9d38 100644
--- a/kexec/arch/ppc64/kexec-ppc64.c
+++ b/kexec/arch/ppc64/kexec-ppc64.c
@@ -31,6 +31,7 @@
 #include "../../kexec.h"
 #include "../../kexec-syscall.h"
 #include "kexec-ppc64.h"
+#include "../../fs2dt.h"
 #include "crashdump-ppc64.h"
 #include <arch/options.h>
 
diff --git a/kexec/arch/ppc64/kexec-ppc64.h b/kexec/arch/ppc64/kexec-ppc64.h
index 920ac46..ad4ab0f 100644
--- a/kexec/arch/ppc64/kexec-ppc64.h
+++ b/kexec/arch/ppc64/kexec-ppc64.h
@@ -1,10 +1,18 @@
 #ifndef KEXEC_PPC64_H
 #define KEXEC_PPC64_H
 
+#include "../../kexec-elf.h"
+
+#include <sys/types.h>
+
 #define MAXBYTES 128
 #define MAX_LINE 160
 #define CORE_TYPE_ELF32 1
 #define CORE_TYPE_ELF64 2
+#define BOOT_BLOCK_VERSION 2
+#define BOOT_BLOCK_LAST_COMP_VERSION 2
+#define HAVE_DYNAMIC_MEMORY
+#define NEED_STRUCTURE_BLOCK_EXTRA_PAD
 
 int setup_memory_ranges(unsigned long kexec_flags);
 
@@ -12,36 +20,15 @@ int elf_ppc64_probe(const char *buf, off_t len);
 int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info);
 void elf_ppc64_usage(void);
-void reserve(unsigned long long where, unsigned long long length);
 
-int create_flatten_tree(char **, off_t *, char *);
 unsigned long my_r2(const struct mem_ehdr *ehdr);
 
 extern uint64_t initrd_base, initrd_size;
 extern int max_memory_ranges;
 extern unsigned char reuse_initrd;
 
-/* boot block version 2 as defined by the linux kernel */
-struct bootblock {
-	unsigned magic,
-		totalsize,
-		off_dt_struct,
-		off_dt_strings,
-		off_mem_rsvmap,
-		version,
-		last_comp_version,
-		boot_physid;
-};
-
 struct arch_options_t {
 	int core_header_type;
 };
 
-typedef struct mem_rgns {
-        unsigned int size;
-        struct memory_range *ranges;
-} mem_rgns_t;
-
-extern mem_rgns_t usablemem_rgns;
-
 #endif /* KEXEC_PPC64_H */
-- 
1.7.12



From dyoung at redhat.com  Fri Sep  7 05:34:33 2012
From: dyoung at redhat.com (Dave Young)
Date: Fri, 07 Sep 2012 17:34:33 +0800
Subject: Getting the kexec on panic
In-Reply-To: <20120906220651.GB1745@cantor.Home>
References: <20120906094336.GJ1943@vicerveza.homeunix.net>
 <20120906220651.GB1745@cantor.Home>
Message-ID: <5049BFA9.4090107@redhat.com>

On 09/07/2012 06:06 AM, Jerry Snitselaar wrote:

> On Thu Sep 06 12, Llu?s Batlle i Rossell wrote:
>> Hello,
>>
>> while I can load immediately a kernel using kexec, when I set it for panic and
>> crash with sysrq-c, the computer hangs.
>>
>> I'm using the nvidia X driver; can it be that it stops the panic handling from
>> working? I don't understand why it would work with normal kexec though, if it
>> were the case.
>>
>> Regards,
>> Llu?s.
> 
> Hi Lluis,
> 
> 
> What kernel are you using? The commit 722bc6b "x86/mm: Fix the size calculation of mapping tables" which started showing up in 3.5-rc1 causes problems for the crash kernel. You might try this patchset[1] from Jacob Shin and see if it resolves the problem for you if you are experiencing your problem on a 3.5-rc1+ kernel.
> 
> [1] https://lkml.org/lkml/2012/8/24/474


He has updated the v5 patch set as below:
https://lkml.org/lkml/2012/8/29/227

> 
> Regards,
> Jerry
> 
>>
>> _______________________________________________
>> kexec mailing list
>> kexec at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/kexec
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec



-- 
Thanks
Dave


From viric at viric.name  Fri Sep  7 05:41:20 2012
From: viric at viric.name (=?iso-8859-1?Q?Llu=EDs?= Batlle i Rossell)
Date: Fri, 7 Sep 2012 11:41:20 +0200
Subject: Getting the kexec on panic
In-Reply-To: <5049BFA9.4090107@redhat.com>
References: <20120906094336.GJ1943@vicerveza.homeunix.net>
 <20120906220651.GB1745@cantor.Home> <5049BFA9.4090107@redhat.com>
Message-ID: <20120907094120.GL1943@vicerveza.homeunix.net>

On Fri, Sep 07, 2012 at 05:34:33PM +0800, Dave Young wrote:
> On 09/07/2012 06:06 AM, Jerry Snitselaar wrote:
> 
> > On Thu Sep 06 12, Llu?s Batlle i Rossell wrote:
> >> Hello,
> >>
> >> while I can load immediately a kernel using kexec, when I set it for panic and
> >> crash with sysrq-c, the computer hangs.
> >>
> >> I'm using the nvidia X driver; can it be that it stops the panic handling from
> >> working? I don't understand why it would work with normal kexec though, if it
> >> were the case.
> >>
> >> Regards,
> >> Llu?s.
> > 
> > Hi Lluis,
> > 
> > 
> > What kernel are you using? The commit 722bc6b "x86/mm: Fix the size calculation of mapping tables" which started showing up in 3.5-rc1 causes problems for the crash kernel. You might try this patchset[1] from Jacob Shin and see if it resolves the problem for you if you are experiencing your problem on a 3.5-rc1+ kernel.
> > 
> > [1] https://lkml.org/lkml/2012/8/24/474
> 
> 
> He has updated the v5 patch set as below:
> https://lkml.org/lkml/2012/8/29/227

I was in 3.5.2 when I tried. Ok, I see these are very recent... I may prepare a
build including that.

Thank you!
Llu?s.


From khalid.aziz at hp.com  Fri Sep  7 10:32:33 2012
From: khalid.aziz at hp.com (Khalid Aziz)
Date: Fri, 07 Sep 2012 08:32:33 -0600
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <20120906202406.GD27209@redhat.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <5047DBA9.8030000@hp.com>  <20120906202406.GD27209@redhat.com>
Message-ID: <1347028353.20255.75.camel@lyra>

On Thu, 2012-09-06 at 16:24 -0400, Vivek Goyal wrote:
> On Wed, Sep 05, 2012 at 05:09:29PM -0600, Khalid Aziz wrote:
> [..]
> > More work will be needed to make this work, for example pass the
> > EFI runtime service memory map from one kernel to the next so we
> > keep it mapped in exact same spot, and other similar mapping issues.
> 
> Hi Khalid,
> 
> This sounds like significant amount of work. So till this work really
> gets merged, noefi is not a bad option. Atleast it will allow us
> to capture dump. And once a generic fix is in, one can remove it and
> build more fancy features which make use of EFI services in second
> kernel?

Hi Vivek,

You are right, it indeed is significant amount of work. I agree noefi is
a reasonable option until EFI is fully working with kexec. As long as
noefi is not seen as long term solution, it makes perfect sense.

Thanks
-- 
Khalid Aziz <khalid.aziz at hp.com>



From khalid.aziz at hp.com  Fri Sep  7 10:37:14 2012
From: khalid.aziz at hp.com (Khalid Aziz)
Date: Fri, 07 Sep 2012 08:37:14 -0600
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <5049B6AD.9000304@redhat.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <5047DBA9.8030000@hp.com> <504815EB.9000701@redhat.com>
 <5048E40E.7040003@hp.com>  <5049B6AD.9000304@redhat.com>
Message-ID: <1347028634.20255.79.camel@lyra>

On Fri, 2012-09-07 at 16:56 +0800, Dave Young wrote:
> Actually in x86 setup code if bootloader do not pass correct efi_info in
> boot_params efi_enabled will be set to 0 automaticlly.
> 

When we kexec a kernel, the EFI signature is missing in the bootloader
signature in boot_params, so kexec'd kernels currently disable EFI
automatically even without noefi in this code:

arch/x86/kernel/setup.c:

733         if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
734                      "EL32", 4)) {
735                 efi_enabled = 1;
736                 efi_64bit = false;
737         } else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signatu     re,             
738                      "EL64", 4)) {
739                 efi_enabled = 1;
740                 efi_64bit = true;
741         }

efi_enabled is initialized to 0.

-- 
Khalid Aziz <khalid.aziz at hp.com>



From khalid.aziz at hp.com  Fri Sep  7 11:16:33 2012
From: khalid.aziz at hp.com (Khalid Aziz)
Date: Fri, 07 Sep 2012 09:16:33 -0600
Subject: Problem with kexec on i386, linux-3.5
In-Reply-To: <502DEB9D.7010308@gmx.at>
References: <500EE046.2000705@gmx.at> <87sjbqjgi8.fsf@xmission.com>
 <502CEA93.7090808@gmx.at> <877gsy4p6h.fsf@xmission.com>
 <502DEB9D.7010308@gmx.at>
Message-ID: <1347030993.20255.93.camel@lyra>

On Fri, 2012-08-17 at 08:58 +0200, Christian Schaubschl?ger wrote:
> >> I bistcted that down to this patch:
> >>
> >> commit b566a22c23327f18ce941ffad0ca907e50a53d41
> >> Author: Khalid Aziz <khalid.aziz at hp.com>
> >> Date:   Fri Apr 27 13:00:33 2012 -0600
> >>
> >>     PCI: disable Bus Master on PCI device shutdown
> >>    
> >>     Disable Bus Master bit on the device in pci_device_shutdown() to ensure PCI
> >>     devices do not continue to DMA data after shutdown.  This can cause memory
> >>     corruption in case of a kexec where the current kernel shuts down and
> >>     transfers control to a new kernel while a PCI device continues to DMA to
> >>     memory that does not belong to it any more in the new kernel.
> >>    
> >>     I have tested this code on two laptops, two workstations and a 16-socket
> >>     server.  kexec worked correctly on all of them.
> >>    
> >>     Signed-off-by: Khalid Aziz <khalid.aziz at hp.com>
> >>     Signed-off-by: Bjorn Helgaas <bhelgaas at google.com>
> >>
> >>
> >> Without this patch, int13 works fine here! If anyone needs more
> >> information, just let me know!
> > Which leads to an interesting conundrum.
> >
> > kexec appears to be more reliable for booting another kernel with this
> > patch applied.  This patch does kill the entier use case of making BIOS
> > calls, and I suspect it also does nasty things to alpha bootloaders.
> >
> > My gut feel is that the trampoline code should reenable bus mastering
> > on the devices that lie behind int13, but I don't know how practical
> > that suggestion is in reality.
> 
> One could make this patch optional... e.g. let kexec tell the running kernel whether or not to disable bus mastering before booting the new one (something like 'kexec --disable-bus-mastering -l /boot/new_kernel.bin'). Don't know if this would be practicable...
> 
> Christian
> 

Sorry, I have been on vacation and hadn't been watching mailing list. I
would not want to make this patch optional. It will be difficult for
most end users to tell if they should kexec with this enabled or not. I
would rather fix issues caused by this patch.

I will spend some time understanding the problem you are seeing and get
back to you.

Thanks
-- 
Khalid Aziz <khalid.aziz at hp.com>



From khalid.aziz at hp.com  Fri Sep  7 16:29:27 2012
From: khalid.aziz at hp.com (Khalid Aziz)
Date: Fri, 07 Sep 2012 14:29:27 -0600
Subject: Problem with kexec on i386, linux-3.5
In-Reply-To: <500EE046.2000705@gmx.at>
References: <500EE046.2000705@gmx.at>
Message-ID: <504A5927.2090605@hp.com>

On 07/24/2012 11:49 AM, Christian Schaubschl?ger wrote:
> Hello list,
>
> I'm not sure if this is the correct place to post this; if it's not, 
> I'd like to apologize.
>
> Here's a short description of my problem:
>
> I have a tiny protected-/real mode program, which I start using kexec 
> (kexec-tools 2.0.3 released 05 April 2012). At some point this program 
> makes a call to extended-int13 to read data from the disk. Now 
> starting with linux-3.5-rc1 (and at least up to linux-3.5) this 
> extended int13 call does not work any more. Apparently the call 
> returns with error code 0x80, which means "timeout (not ready)".
>
> I have two machines here, both with Intel chipsets (one CougarPoint, 
> one older ICH7-M), and I see the same behaviour on both machines.
>
> When I use older kernels (starting from 2.6.something up to 3.4.6), 
> everything works fine.
>
> Now I'm not sure if this is a kernel issue, or a kexec issue, or a 
> mistake by myself. Maybe someone has a hint for me...
>
> If required, of course, I can provide more detailed information about 
> my hardware, kernel config, etc. (since I'm not sure if this is the 
> correct place, I wanted to keep this message short for now).
>

Hello Christian,

Are you not loading the driver for your disk drive controller when the 
new kernel boots up, even though you are not using the driver for disk 
I/O? If yes, the driver should have re-enabled Bus Master bit in its 
init routine. If you are loading the driver, which driver is it? I can 
take a look at it and see if there is anything missing in the 
initialization routine. Can you also include output from "lspci -v" from 
your machine?

Thanks
-- 
Khalid


From horms at verge.net.au  Sun Sep  9 20:05:50 2012
From: horms at verge.net.au (Simon Horman)
Date: Mon, 10 Sep 2012 09:05:50 +0900
Subject: [PATCH 0/7] Add device-tree support to kexec-tools for ARM
In-Reply-To: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
References: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
Message-ID: <20120910000550.GI30480@verge.net.au>

On Fri, Sep 07, 2012 at 10:11:19AM +0100, Matthew Leach wrote:
> Hi all,
> 
> Running a kexec() on ARM platforms has become an issue as information
> about the platform that is presented via device-tree is required to
> boot newer kernels.
> 
> The ATAGs kernel code is re-used, replacing the ATAGs with a
> device-tree blob so that only kexec-tools needs to be changed. There
> are two options for generating a dtb to be passed to the kernel from
> kexec-tools: 1) Read in the device-tree that is exposed in
> /proc/device-tree and flatten this out into a dtb.  2) Allow the user
> to specify a dtb file on the command line.  These blobs are then
> loaded into memory before the kernel image and the address passed
> through to r2, as stated in the ARM booting documentation.
> 
> These patches depend upon a kernel patch, namely:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2012-September/118275.html
> 
> Simon - you are welcome to add your signed-off-by to my final patch as
> I incorporated bits of your final patch into mine.

Sure, I'll add the sign-off as part of merging the changes.

What I have in mind is to to merge the non ppc64/powerpc patches,
that is 5 of the 7 patches. I'm a but unsure how the kernel-side of things
will pan out, but an incremental patch can be made to kexec-tools
if needed and this series shouldn't break any existing support
Does that work for you?

> Matt
> 
> Matthew Leach (1):
>   ARM: Add device tree support to the ARM platform
> 
> Simon Horman (6):
>   libfdt: Move from kexec/arch/ppc/libfdt/ to kexec/libfdt/
>   kexec-elf.h: Include headers for types used
>   fs2dt: Add a generic copy of fs2dt
>   ppc64: Move 64bit powerpc to use generic fs2dt code
>   powerpc: Move 32bit powerpc to use generic fs2dt code
>   arm: Make use of memory_ranges
> 
>  kexec/Makefile                                |   6 +
>  kexec/arch/arm/Makefile                       |  13 +
>  kexec/arch/arm/crashdump-arm.c                |  45 ++-
>  kexec/arch/arm/crashdump-arm.h                |   2 +
>  kexec/arch/arm/include/arch/options.h         |   6 +-
>  kexec/arch/arm/kexec-arm.h                    |   7 +
>  kexec/arch/arm/kexec-zImage-arm.c             |  87 ++++-
>  kexec/arch/ppc/Makefile                       |  17 +-
>  kexec/arch/ppc/crashdump-powerpc.c            |   2 +-
>  kexec/arch/ppc/crashdump-powerpc.h            |   2 +
>  kexec/arch/ppc/fs2dt.c                        | 450 --------------------------
>  kexec/arch/ppc/kexec-elf-ppc.c                |   2 -
>  kexec/arch/ppc/kexec-ppc.h                    |  26 +-
>  kexec/arch/ppc/kexec-uImage-ppc.c             |   3 -
>  kexec/arch/ppc64/Makefile                     |   7 +-
>  kexec/arch/ppc64/crashdump-ppc64.c            |   3 +-
>  kexec/arch/ppc64/crashdump-ppc64.h            |   4 +
>  kexec/arch/ppc64/kexec-elf-ppc64.c            |   4 +-
>  kexec/arch/ppc64/kexec-ppc64.c                |   1 +
>  kexec/arch/ppc64/kexec-ppc64.h                |  29 +-
>  kexec/arch_reuse_initrd.c                     |   2 +
>  kexec/{arch/ppc64 => }/fs2dt.c                | 277 +++++++++-------
>  kexec/fs2dt.h                                 |  38 +++
>  kexec/kexec-elf.h                             |   3 +
>  kexec/kexec.h                                 |   5 +
>  kexec/{arch/ppc => }/libfdt/Makefile.libfdt   |   8 +-
>  kexec/{arch/ppc => }/libfdt/TODO              |   0
>  kexec/{arch/ppc => }/libfdt/fdt.c             |   0
>  kexec/{arch/ppc => }/libfdt/fdt.h             |   0
>  kexec/{arch/ppc => }/libfdt/fdt_ro.c          |   0
>  kexec/{arch/ppc => }/libfdt/fdt_rw.c          |   0
>  kexec/{arch/ppc => }/libfdt/fdt_strerror.c    |   0
>  kexec/{arch/ppc => }/libfdt/fdt_sw.c          |   0
>  kexec/{arch/ppc => }/libfdt/fdt_wip.c         |   0
>  kexec/{arch/ppc => }/libfdt/libfdt.h          |   0
>  kexec/{arch/ppc => }/libfdt/libfdt_env.h      |   0
>  kexec/{arch/ppc => }/libfdt/libfdt_internal.h |   0
>  37 files changed, 392 insertions(+), 657 deletions(-)
>  delete mode 100644 kexec/arch/ppc/fs2dt.c
>  rename kexec/{arch/ppc64 => }/fs2dt.c (77%)
>  create mode 100644 kexec/fs2dt.h
>  rename kexec/{arch/ppc => }/libfdt/Makefile.libfdt (60%)
>  rename kexec/{arch/ppc => }/libfdt/TODO (100%)
>  rename kexec/{arch/ppc => }/libfdt/fdt.c (100%)
>  rename kexec/{arch/ppc => }/libfdt/fdt.h (100%)
>  rename kexec/{arch/ppc => }/libfdt/fdt_ro.c (100%)
>  rename kexec/{arch/ppc => }/libfdt/fdt_rw.c (100%)
>  rename kexec/{arch/ppc => }/libfdt/fdt_strerror.c (100%)
>  rename kexec/{arch/ppc => }/libfdt/fdt_sw.c (100%)
>  rename kexec/{arch/ppc => }/libfdt/fdt_wip.c (100%)
>  rename kexec/{arch/ppc => }/libfdt/libfdt.h (100%)
>  rename kexec/{arch/ppc => }/libfdt/libfdt_env.h (100%)
>  rename kexec/{arch/ppc => }/libfdt/libfdt_internal.h (100%)
> 
> -- 
> 1.7.12
> 


From kaneshige.kenji at jp.fujitsu.com  Sun Sep  9 22:34:42 2012
From: kaneshige.kenji at jp.fujitsu.com (Kaneshige, Kenji)
Date: Mon, 10 Sep 2012 02:34:42 +0000
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <50473306.1070803@jp.fujitsu.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com> <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com> <50473306.1070803@jp.fujitsu.com>
Message-ID: <4A338DB2991D2A44B9A44B8718AECF650A4AA6BF@G01JPEXMBYT03>

> -----Original Message-----
> From: linux-pci-owner at vger.kernel.org
> [mailto:linux-pci-owner at vger.kernel.org] On Behalf Of Takao Indoh
> Sent: Wednesday, September 05, 2012 8:10 PM
> To: vgoyal at redhat.com
> Cc: kexec at lists.infradead.org; linux-kernel at vger.kernel.org;
> linux-pci at vger.kernel.org; bhelgaas at google.com; hbabu at us.ibm.com; Ishii,
> Hironobu/?? ??; martin.wilck at ts.fujitsu.com
> Subject: Re: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
> with iommu
> 
> (2012/08/07 5:39), Vivek Goyal wrote:
> > On Mon, Aug 06, 2012 at 01:30:47PM +0900, Takao Indoh wrote:
> >> Hi Vivek,
> >>
> >> (2012/08/03 20:46), Vivek Goyal wrote:
> >>> On Fri, Aug 03, 2012 at 08:24:31PM +0900, Takao Indoh wrote:
> >>>> Hi all,
> >>>>
> >>>> This patch adds kernel parameter "reset_pcie_devices" which resets
> PCIe
> >>>> devices at boot time to address DMA problem on kdump with iommu. When
> >>>> this parameter is specified, a hot reset is triggered on each PCIe
> root
> >>>> port and downstream port to reset its downstream endpoint.
> >>>
> >>> Hi Takao,
> >>>
> >>> Why not use existing "reset_devices" parameter instead of introducing
> >>> a new one?
> >>
> >> "reset_devices" is used for each driver to reset their own device, and
> >> this patch resets all devices forcibly, so I thought they were different
> >> things.
> >
> > Yes reset_devices currently is used for driver to reset its device. I
> > thought one could very well extend its reach to reset pci express devices
> > at bus level.
> >
> > Having them separate is not going to be much useful from kdump
> > perspective. We will end up passing both reset_devices and
> > reset_pcie_devices to second kernel whill lead to bus level reset as well
> > as device level reset.
> >
> > Ideal situation would be that somehow detect that bus level reset has
> been
> > done and skip device level reset (assuming bus level reset obviates the
> > need of device level reset, please correct me if that's not the case).
> >
> > After pcie reset, can we store the state in a variable and drivers can
> > use that variable to check if PCIe level reset was done or not. If yes,
> > skip device level reset (Assuming driver knows that device is on a
> > PCIe slot).
> >
> > In that case we will not have to introduce new kernel command line, and
> > also avoid double reset?
> 
> I found a problem when testing my patch on some machines.
> 
> Originally there are two problems in kdump kernel when iommu is enabled;
> DMAR error and PCI SERR. I thought they are fixed by my patch, but I
> noticed that PCI SERR is still detected after applying the patch. It
> seems that something happens when Interrupt Remapping is initialized in
> kdump kernel.

I'm not sure, but I guess the PCI SERR might be caused as follows.

- The 1st kernel enables interrupt remapping. The MSI(-X) address and
  data registers of PCI devices are programmed in remappable format.

- At the beginning of 2nd kernel, interrupt remapping is still active.
  And then it is disabled by enable_IR() function for initialization.

- PCI device generate an interrupt. At this moment, interrupt remapping
  is not enabled yet. On the other hand, MSI(-X) address and data of this
  interrupt is in remappable format because those are programmed by 1st
  kernel. I guess this might be a cause of PCI SERR.

I guess clearing command register or disabling MSI before interrupt
remapping initialization in 2nd kernel might solve the PCI SERR problem.

Regards,
Kenji Kaneshige


> 
> Therefore resetting devices has to be done before enable_IR() is
> called. I have three ideas for it.
> 
>   (i) Resetting devices in 1st kernel(panic kernel)
>   We can reset devices before jumping into 2nd kernel. Of course it may
>   be dangerous to scan pci device tree and call PCI functions in panic'd
>   kernel. Beforehand we need to collect device information so that only
>   minimal code could run on panic.
> 
>   (ii) Resetting devices in purgatory
>   It seems to be be appropriate place to do this, but I'm not sure
>   where I can save/restore PCI config when resetting devices in
>   purgatory.
> 
>   (iii) Resetting devices in 2nd kernel(kdump kernel)
>   Important point is to do reset before enable_IR() is called as I wrote
>   above. I think I should add new function to do reset into
>   arch/x86/pci/early.c and call it in setup_arch like
>   early_dump_pci_devices() or early_quirks().
> 
> Any comments?
> 
> Thanks,
> Takao Indoh
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


From indou.takao at jp.fujitsu.com  Mon Sep 10 02:35:20 2012
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Mon, 10 Sep 2012 15:35:20 +0900
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <4A338DB2991D2A44B9A44B8718AECF650A4AA6BF@G01JPEXMBYT03>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com> <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com> <50473306.1070803@jp.fujitsu.com>
 <4A338DB2991D2A44B9A44B8718AECF650A4AA6BF@G01JPEXMBYT03>
Message-ID: <504D8A28.9090105@jp.fujitsu.com>

(2012/09/10 11:34), Kaneshige, Kenji wrote:
>> -----Original Message-----
>> From: linux-pci-owner at vger.kernel.org
>> [mailto:linux-pci-owner at vger.kernel.org] On Behalf Of Takao Indoh
>> Sent: Wednesday, September 05, 2012 8:10 PM
>> To: vgoyal at redhat.com
>> Cc: kexec at lists.infradead.org; linux-kernel at vger.kernel.org;
>> linux-pci at vger.kernel.org; bhelgaas at google.com; hbabu at us.ibm.com; Ishii,
>> Hironobu/?? ??; martin.wilck at ts.fujitsu.com
>> Subject: Re: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
>> with iommu
>>
>> (2012/08/07 5:39), Vivek Goyal wrote:
>>> On Mon, Aug 06, 2012 at 01:30:47PM +0900, Takao Indoh wrote:
>>>> Hi Vivek,
>>>>
>>>> (2012/08/03 20:46), Vivek Goyal wrote:
>>>>> On Fri, Aug 03, 2012 at 08:24:31PM +0900, Takao Indoh wrote:
>>>>>> Hi all,
>>>>>>
>>>>>> This patch adds kernel parameter "reset_pcie_devices" which resets
>> PCIe
>>>>>> devices at boot time to address DMA problem on kdump with iommu. When
>>>>>> this parameter is specified, a hot reset is triggered on each PCIe
>> root
>>>>>> port and downstream port to reset its downstream endpoint.
>>>>>
>>>>> Hi Takao,
>>>>>
>>>>> Why not use existing "reset_devices" parameter instead of introducing
>>>>> a new one?
>>>>
>>>> "reset_devices" is used for each driver to reset their own device, and
>>>> this patch resets all devices forcibly, so I thought they were different
>>>> things.
>>>
>>> Yes reset_devices currently is used for driver to reset its device. I
>>> thought one could very well extend its reach to reset pci express devices
>>> at bus level.
>>>
>>> Having them separate is not going to be much useful from kdump
>>> perspective. We will end up passing both reset_devices and
>>> reset_pcie_devices to second kernel whill lead to bus level reset as well
>>> as device level reset.
>>>
>>> Ideal situation would be that somehow detect that bus level reset has
>> been
>>> done and skip device level reset (assuming bus level reset obviates the
>>> need of device level reset, please correct me if that's not the case).
>>>
>>> After pcie reset, can we store the state in a variable and drivers can
>>> use that variable to check if PCIe level reset was done or not. If yes,
>>> skip device level reset (Assuming driver knows that device is on a
>>> PCIe slot).
>>>
>>> In that case we will not have to introduce new kernel command line, and
>>> also avoid double reset?
>>
>> I found a problem when testing my patch on some machines.
>>
>> Originally there are two problems in kdump kernel when iommu is enabled;
>> DMAR error and PCI SERR. I thought they are fixed by my patch, but I
>> noticed that PCI SERR is still detected after applying the patch. It
>> seems that something happens when Interrupt Remapping is initialized in
>> kdump kernel.
> 
> I'm not sure, but I guess the PCI SERR might be caused as follows.
> 
> - The 1st kernel enables interrupt remapping. The MSI(-X) address and
>    data registers of PCI devices are programmed in remappable format.
> 
> - At the beginning of 2nd kernel, interrupt remapping is still active.
>    And then it is disabled by enable_IR() function for initialization.
> 
> - PCI device generate an interrupt. At this moment, interrupt remapping
>    is not enabled yet. On the other hand, MSI(-X) address and data of this
>    interrupt is in remappable format because those are programmed by 1st
>    kernel. I guess this might be a cause of PCI SERR.
> 
> I guess clearing command register or disabling MSI before interrupt
> remapping initialization in 2nd kernel might solve the PCI SERR problem.

Thank you for your comment. That makes sense.

Though I think clearing bus master bit is enough, do you think I need to clear
all command register bit not only bus master? 

Thanks,
Takao Indoh


> Regards,
> Kenji Kaneshige
> 
> 
>>
>> Therefore resetting devices has to be done before enable_IR() is
>> called. I have three ideas for it.
>>
>>    (i) Resetting devices in 1st kernel(panic kernel)
>>    We can reset devices before jumping into 2nd kernel. Of course it may
>>    be dangerous to scan pci device tree and call PCI functions in panic'd
>>    kernel. Beforehand we need to collect device information so that only
>>    minimal code could run on panic.
>>
>>    (ii) Resetting devices in purgatory
>>    It seems to be be appropriate place to do this, but I'm not sure
>>    where I can save/restore PCI config when resetting devices in
>>    purgatory.
>>
>>    (iii) Resetting devices in 2nd kernel(kdump kernel)
>>    Important point is to do reset before enable_IR() is called as I wrote
>>    above. I think I should add new function to do reset into
>>    arch/x86/pci/early.c and call it in setup_arch like
>>    early_dump_pci_devices() or early_quirks().
>>
>> Any comments?
>>
>> Thanks,
>> Takao Indoh
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 



From christian.schaubschlaeger at gmx.at  Mon Sep 10 02:00:14 2012
From: christian.schaubschlaeger at gmx.at (=?ISO-8859-1?Q?Christian_Schaubschl=E4ger?=)
Date: Mon, 10 Sep 2012 08:00:14 +0200
Subject: Problem with kexec on i386, linux-3.5
In-Reply-To: <504A5927.2090605@hp.com>
References: <500EE046.2000705@gmx.at> <504A5927.2090605@hp.com>
Message-ID: <504D81EE.7070409@gmx.at>


Hello Khalid,

> Are you not loading the driver for your disk drive controller when the 
> new kernel boots up, even though you are not using the driver for disk 
> I/O? If yes, the driver should have re-enabled Bus Master bit in its 
> init routine. If you are loading the driver, which driver is it? I can 
> take a look at it and see if there is anything missing in the 
> initialization routine. Can you also include output from "lspci -v" from 
> your machine?

I'm not loading any drivers in my new kernel, I'm just doing pure BIOS disk I/O using Int13 calls (the program I start using kexec I would not actually call a 'kernel', it's just a very tiny piece of software which does some disk I/O and output on the screen).

Attached you find the output of lspci -v

Best regards
Christian


-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: lspic_d520.txt
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20120910/db9df3ce/attachment-0001.txt>

From will.deacon at arm.com  Mon Sep 10 04:53:58 2012
From: will.deacon at arm.com (Will Deacon)
Date: Mon, 10 Sep 2012 09:53:58 +0100
Subject: [PATCH 0/7] Add device-tree support to kexec-tools for ARM
In-Reply-To: <20120910000550.GI30480@verge.net.au>
References: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
 <20120910000550.GI30480@verge.net.au>
Message-ID: <20120910085358.GA21650@mudshark.cambridge.arm.com>

On Mon, Sep 10, 2012 at 01:05:50AM +0100, Simon Horman wrote:
> On Fri, Sep 07, 2012 at 10:11:19AM +0100, Matthew Leach wrote:
> > Hi all,
> > 
> > Running a kexec() on ARM platforms has become an issue as information
> > about the platform that is presented via device-tree is required to
> > boot newer kernels.
> > 
> > The ATAGs kernel code is re-used, replacing the ATAGs with a
> > device-tree blob so that only kexec-tools needs to be changed. There
> > are two options for generating a dtb to be passed to the kernel from
> > kexec-tools: 1) Read in the device-tree that is exposed in
> > /proc/device-tree and flatten this out into a dtb.  2) Allow the user
> > to specify a dtb file on the command line.  These blobs are then
> > loaded into memory before the kernel image and the address passed
> > through to r2, as stated in the ARM booting documentation.
> > 
> > These patches depend upon a kernel patch, namely:
> > http://lists.infradead.org/pipermail/linux-arm-kernel/2012-September/118275.html
> > 
> > Simon - you are welcome to add your signed-off-by to my final patch as
> > I incorporated bits of your final patch into mine.
> 
> Sure, I'll add the sign-off as part of merging the changes.
> 
> What I have in mind is to to merge the non ppc64/powerpc patches,
> that is 5 of the 7 patches. I'm a but unsure how the kernel-side of things
> will pan out, but an incremental patch can be made to kexec-tools
> if needed and this series shouldn't break any existing support
> Does that work for you?

Sounds good to me, I'll pursue the kernel-side changes for ARM.

Cheers,

Will


From daniel.kiper at oracle.com  Mon Sep 10 07:57:46 2012
From: daniel.kiper at oracle.com (Daniel Kiper)
Date: Mon, 10 Sep 2012 13:57:46 +0200
Subject: [PATCH 2/7] xen: Rename e820_to_kexec_type() to
 xen_e820_to_kexec_type() and export it
In-Reply-To: <1347278271-5211-2-git-send-email-daniel.kiper@oracle.com>
References: <1347278271-5211-1-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-2-git-send-email-daniel.kiper@oracle.com>
Message-ID: <1347278271-5211-3-git-send-email-daniel.kiper@oracle.com>

Rename e820_to_kexec_type() to xen_e820_to_kexec_type() and export it.

Signed-off-by: Daniel Kiper <daniel.kiper at oracle.com>
---
 kexec/arch/i386/kexec-x86-common.c |    6 +++---
 kexec/arch/i386/kexec-x86.h        |    2 ++
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/kexec/arch/i386/kexec-x86-common.c b/kexec/arch/i386/kexec-x86-common.c
index 609d35d..02471a8 100644
--- a/kexec/arch/i386/kexec-x86-common.c
+++ b/kexec/arch/i386/kexec-x86-common.c
@@ -151,7 +151,7 @@ static int get_memory_ranges_sysfs(struct memory_range **range, int *ranges)
 }
 
 #ifdef HAVE_LIBXENCTRL
-static unsigned e820_to_kexec_type(uint32_t type)
+unsigned xen_e820_to_kexec_type(uint32_t type)
 {
 	switch (type) {
 		case E820_RAM:
@@ -213,7 +213,7 @@ static int get_memory_ranges_xen(struct memory_range **range, int *ranges)
 	for (i = 0; i < rc; ++i) {
 		memory_range[i].start = e820entries[i].addr;
 		memory_range[i].end = e820entries[i].addr + e820entries[i].size;
-		memory_range[i].type = e820_to_kexec_type(e820entries[i].type);
+		memory_range[i].type = xen_e820_to_kexec_type(e820entries[i].type);
 	}
 
 	qsort(memory_range, rc, sizeof(struct memory_range), compare_ranges);
@@ -289,7 +289,7 @@ static int get_memory_ranges_xen(struct memory_range **range, int *ranges)
 	for (i = 0; i < xen_memory_map->nr_entries; ++i) {
 		memory_range[i].start = e820entries[i].addr;
 		memory_range[i].end = e820entries[i].addr + e820entries[i].size;
-		memory_range[i].type = e820_to_kexec_type(e820entries[i].type);
+		memory_range[i].type = xen_e820_to_kexec_type(e820entries[i].type);
 	}
 
 	qsort(memory_range, xen_memory_map->nr_entries, sizeof(struct memory_range), compare_ranges);
diff --git a/kexec/arch/i386/kexec-x86.h b/kexec/arch/i386/kexec-x86.h
index dfcc51d..5aa2a46 100644
--- a/kexec/arch/i386/kexec-x86.h
+++ b/kexec/arch/i386/kexec-x86.h
@@ -81,4 +81,6 @@ int nbi_probe(const char *buf, off_t len);
 int nbi_load(int argc, char **argv, const char *buf, off_t len,
 	struct kexec_info *info);
 void nbi_usage(void);
+
+extern unsigned xen_e820_to_kexec_type(uint32_t type);
 #endif /* KEXEC_X86_H */
-- 
1.5.6.5



From daniel.kiper at oracle.com  Mon Sep 10 07:57:47 2012
From: daniel.kiper at oracle.com (Daniel Kiper)
Date: Mon, 10 Sep 2012 13:57:47 +0200
Subject: [PATCH 3/7] kexec: Move crash kernel area placement and size
 detection to is_crashkernel_mem_reserved()
In-Reply-To: <1347278271-5211-3-git-send-email-daniel.kiper@oracle.com>
References: <1347278271-5211-1-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-2-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-3-git-send-email-daniel.kiper@oracle.com>
Message-ID: <1347278271-5211-4-git-send-email-daniel.kiper@oracle.com>

Move crash kernel area placement and size detection
from get_crash_memory_ranges() to is_crashkernel_mem_reserved().
Former one will not be used by fixed Xen kdump support.

Signed-off-by: Daniel Kiper <daniel.kiper at oracle.com>
---
 kexec/arch/i386/crashdump-x86.c |   17 ++++++++---------
 1 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 2af090c..ec9432b 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -212,13 +212,6 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
 		/* Only Dumping memory of type System RAM. */
 		if (memcmp(str, "System RAM\n", 11) == 0) {
 			type = RANGE_RAM;
-		} else if (memcmp(str, "Crash kernel\n", 13) == 0) {
-				/* Reserved memory region. New kernel can
-				 * use this region to boot into. */
-				crash_reserved_mem.start = start;
-				crash_reserved_mem.end = end;
-				crash_reserved_mem.type = RANGE_RAM;
-				continue;
 		} else if (memcmp(str, "ACPI Tables\n", 12) == 0) {
 			/*
 			 * ACPI Tables area need to be passed to new
@@ -849,6 +842,12 @@ int is_crashkernel_mem_reserved(void)
 {
 	uint64_t start, end;
 
-	return parse_iomem_single("Crash kernel\n", &start, &end) == 0 ?
-	  (start != end) : 0;
+	if (parse_iomem_single("Crash kernel\n", &start, &end) || start == end)
+		return 0;
+
+	crash_reserved_mem.start = start;
+	crash_reserved_mem.end = end;
+	crash_reserved_mem.type = RANGE_RAM;
+
+	return 1;
 }
-- 
1.5.6.5



From daniel.kiper at oracle.com  Mon Sep 10 07:57:44 2012
From: daniel.kiper at oracle.com (Daniel Kiper)
Date: Mon, 10 Sep 2012 13:57:44 +0200
Subject: [PATCH 0/7] kdump: Xen fixes
Message-ID: <1347278271-5211-1-git-send-email-daniel.kiper@oracle.com>

Hi,

Here I am sending Xen kdump fixes.

Daniel

Daniel Kiper (7):
      kexec: Define some constants and structures conditionally
      xen: Rename e820_to_kexec_type() to xen_e820_to_kexec_type() and export it
      kexec: Move crash kernel area placement and size detection to is_crashkernel_mem_reserved()
      kexec: Add segregate_lowmem_region()
      kexec: Get backup area start address and size directly from mem_range
      kexec: Move crash memory ranges logging
      xen: Fix Xen kdump support

 include/x86/x86-linux.h            |    7 +-
 kexec/arch/i386/crashdump-x86.c    |  322 +++++++++++++++++++++++++++--------
 kexec/arch/i386/kexec-x86-common.c |    6 +-
 kexec/arch/i386/kexec-x86.h        |    2 +
 4 files changed, 259 insertions(+), 78 deletions(-)


From daniel.kiper at oracle.com  Mon Sep 10 07:57:45 2012
From: daniel.kiper at oracle.com (Daniel Kiper)
Date: Mon, 10 Sep 2012 13:57:45 +0200
Subject: [PATCH 1/7] kexec: Define some constants and structures conditionally
In-Reply-To: <1347278271-5211-1-git-send-email-daniel.kiper@oracle.com>
References: <1347278271-5211-1-git-send-email-daniel.kiper@oracle.com>
Message-ID: <1347278271-5211-2-git-send-email-daniel.kiper@oracle.com>

Some definitions in include/x86/x86-linux.h conflicts
with definitions placed in Xen headers. Make them
conditional. This patch is required by future
Xen kdump fixes.

Signed-off-by: Daniel Kiper <daniel.kiper at oracle.com>
---
 include/x86/x86-linux.h |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/include/x86/x86-linux.h b/include/x86/x86-linux.h
index 2ebcc3a..27af02b 100644
--- a/include/x86/x86-linux.h
+++ b/include/x86/x86-linux.h
@@ -4,13 +4,17 @@
 #define TENATIVE 0 /* Code that is tenatively correct but hasn't yet been officially accepted */
 
 #define E820MAP	0x2d0		/* our map */
-#define E820MAX	128		/* number of entries in E820MAP */
 #define E820NR	0x1e8		/* # entries in E820MAP */
 
+#ifndef E820MAX
+#define E820MAX	128		/* number of entries in E820MAP */
+#endif
+
 #ifndef ASSEMBLY
 
 #define PACKED __attribute__((packed))
 
+#ifndef E820_RAM
 struct e820entry {
 	uint64_t addr;	/* start of memory segment */
 	uint64_t size;	/* size of memory segment */
@@ -20,6 +24,7 @@ struct e820entry {
 #define E820_ACPI	3 /* usable as RAM once ACPI tables have been read */
 #define E820_NVS	4
 } PACKED;
+#endif
 
 /* FIXME expand on drive_info_)struct... */
 struct drive_info_struct {
-- 
1.5.6.5



From daniel.kiper at oracle.com  Mon Sep 10 07:57:49 2012
From: daniel.kiper at oracle.com (Daniel Kiper)
Date: Mon, 10 Sep 2012 13:57:49 +0200
Subject: [PATCH 5/7] kexec: Get backup area start address and size directly
 from mem_range
In-Reply-To: <1347278271-5211-5-git-send-email-daniel.kiper@oracle.com>
References: <1347278271-5211-1-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-2-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-3-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-4-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-5-git-send-email-daniel.kiper@oracle.com>
Message-ID: <1347278271-5211-6-git-send-email-daniel.kiper@oracle.com>

Get backup area start address and size directly from mem_range.
Under Xen /proc/iomem contains invalid values.

Signed-off-by: Daniel Kiper <daniel.kiper at oracle.com>
---
 kexec/arch/i386/crashdump-x86.c |   55 +++++++++++++-------------------------
 1 files changed, 19 insertions(+), 36 deletions(-)

diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 77a1329..56ef59e 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -667,44 +667,28 @@ static int cmdline_add_memmap_acpi(char *cmdline, unsigned long start,
 	return 0;
 }
 
-static void get_backup_area(unsigned long *start, unsigned long *end)
+static void get_backup_area(struct kexec_info *info,
+				struct memory_range *range, int ranges)
 {
-	const char *iomem = proc_iomem();
-	char line[MAX_LINE];
-	FILE *fp;
+	int i;
 
-	fp = fopen(iomem, "r");
-	if (!fp) {
-		fprintf(stderr, "Cannot open %s: %s\n",
-			iomem, strerror(errno));
-		return;
-	}
+	/* Look for first 640 KiB RAM region. */
+	for (i = 0; i < ranges; ++i) {
+		if (range[i].type != RANGE_RAM || range[i].end > 0xa0000)
+			continue;
 
-	while(fgets(line, sizeof(line), fp) != 0) {
-		char *str;
-		int count, consumed;
-		unsigned long mstart, mend;
+		info->backup_src_start = range[i].start;
+		info->backup_src_size = range[i].end - range[i].start + 1;
 
-		count = sscanf(line, "%lx-%lx : %n",
-			&mstart, &mend, &consumed);
-		if (count != 2)
-			continue;
-		str = line + consumed;
-		dbgprintf("%016lx-%016lx : %s",
-			mstart, mend, str);
-
-		/* Hopefully there is only one RAM region in the first 640K */
-		if (memcmp(str, "System RAM\n", 11) == 0 && mend <= 0xa0000 ) {
-			dbgprintf("%s: %016lx-%016lx : %s", __func__, mstart, mend, str);
-			*start = mstart;
-			*end = mend;
-			fclose(fp);
-			return;
-		}
+		dbgprintf("%s: %016llx-%016llx : System RAM\n", __func__,
+						range[i].start, range[i].end);
+
+		return;
 	}
-	*start = BACKUP_SRC_START;
-	*end = BACKUP_SRC_END;
-	fclose(fp);
+
+	/* First 640 KiB RAM region not found. Assume defaults. */
+	info->backup_src_start = BACKUP_SRC_START;
+	info->backup_src_size = BACKUP_SRC_END - BACKUP_SRC_START + 1;
 }
 
 /* Loads additional segments in case of a panic kernel is being loaded.
@@ -720,15 +704,12 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
 	struct memory_range *mem_range, *memmap_p;
 	struct crash_elf_info elf_info;
 	unsigned kexec_arch;
-	unsigned long tmp_backup_end = 0;
 
 	memset(&elf_info, 0x0, sizeof(elf_info));
 
 	/* Constant parts of the elf_info */
 	memset(&elf_info, 0, sizeof(elf_info));
 	elf_info.data             = ELFDATA2LSB;
-	get_backup_area(&info->backup_src_start, &tmp_backup_end);
-	info->backup_src_size = tmp_backup_end - info->backup_src_start + 1;
 
 	/* Get the architecture of the running kernel */
 	kexec_arch = info->kexec_flags & KEXEC_ARCH_MASK;
@@ -756,6 +737,8 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
 				    elf_info.lowmem_limit) < 0)
 		return -1;
 
+	get_backup_area(info, mem_range, nr_ranges);
+
 	/*
 	 * if the core type has not been set on command line, set it here
 	 * automatically
-- 
1.5.6.5



From daniel.kiper at oracle.com  Mon Sep 10 07:57:50 2012
From: daniel.kiper at oracle.com (Daniel Kiper)
Date: Mon, 10 Sep 2012 13:57:50 +0200
Subject: [PATCH 6/7] kexec: Move crash memory ranges logging
In-Reply-To: <1347278271-5211-6-git-send-email-daniel.kiper@oracle.com>
References: <1347278271-5211-1-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-2-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-3-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-4-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-5-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-6-git-send-email-daniel.kiper@oracle.com>
Message-ID: <1347278271-5211-7-git-send-email-daniel.kiper@oracle.com>

Move crash memory ranges logging from get_crash_memory_ranges()
to load_crashdump_segments(). This solution will be used by
fixed Xen kdump support, too.

Signed-off-by: Daniel Kiper <daniel.kiper at oracle.com>
---
 kexec/arch/i386/crashdump-x86.c |   13 +++++--------
 1 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index 56ef59e..c6b9354 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -270,14 +270,6 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
 	*range = crash_memory_range;
 	*ranges = memory_ranges;
 
-	int i;
-	dbgprintf("CRASH MEMORY RANGES\n");
-	for(i = 0; i < memory_ranges; i++) {
-		start = crash_memory_range[i].start;
-		end = crash_memory_range[i].end;
-		dbgprintf("%016Lx-%016Lx\n", start, end);
-	}
-
 	return 0;
 }
 
@@ -739,6 +731,11 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
 
 	get_backup_area(info, mem_range, nr_ranges);
 
+	dbgprintf("CRASH MEMORY RANGES\n");
+
+	for(i = 0; i < nr_ranges; ++i)
+		dbgprintf("%016Lx-%016Lx\n", mem_range[i].start, mem_range[i].end);
+
 	/*
 	 * if the core type has not been set on command line, set it here
 	 * automatically
-- 
1.5.6.5



From daniel.kiper at oracle.com  Mon Sep 10 07:57:48 2012
From: daniel.kiper at oracle.com (Daniel Kiper)
Date: Mon, 10 Sep 2012 13:57:48 +0200
Subject: [PATCH 4/7] kexec: Add segregate_lowmem_region()
In-Reply-To: <1347278271-5211-4-git-send-email-daniel.kiper@oracle.com>
References: <1347278271-5211-1-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-2-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-3-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-4-git-send-email-daniel.kiper@oracle.com>
Message-ID: <1347278271-5211-5-git-send-email-daniel.kiper@oracle.com>

Extract code segregating lowmem region and move it to new
segregate_lowmem_region(). This function will be used by
fixed Xen kdump support, too.

Signed-off-by: Daniel Kiper <daniel.kiper at oracle.com>
---
 kexec/arch/i386/crashdump-x86.c |   38 +++++++++++++++++++++++++++-----------
 1 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index ec9432b..77a1329 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -159,6 +159,7 @@ static int get_kernel_vaddr_and_size(struct kexec_info *UNUSED(info),
 }
 
 /* Forward Declaration. */
+static void segregate_lowmem_region(int *nr_ranges, unsigned long lowmem_limit);
 static int exclude_region(int *nr_ranges, uint64_t start, uint64_t end);
 
 /* Stores a sorted list of RAM memory ranges for which to create elf headers.
@@ -235,19 +236,10 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
 		crash_memory_range[memory_ranges].start = start;
 		crash_memory_range[memory_ranges].end = end;
 		crash_memory_range[memory_ranges].type = type;
-		memory_ranges++;
 
-		/* Segregate linearly mapped region. */
-		if (lowmem_limit &&
-		    (lowmem_limit - 1) >= start && (lowmem_limit - 1) <= end) {
-			crash_memory_range[memory_ranges-1].end = lowmem_limit -1;
+		segregate_lowmem_region(&memory_ranges, lowmem_limit);
 
-			/* Add segregated region. */
-			crash_memory_range[memory_ranges].start = lowmem_limit;
-			crash_memory_range[memory_ranges].end = end;
-			crash_memory_range[memory_ranges].type = type;
-			memory_ranges++;
-		}
+		memory_ranges++;
 	}
 	fclose(fp);
 	if (kexec_flags & KEXEC_PRESERVE_CONTEXT) {
@@ -289,6 +281,30 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
 	return 0;
 }
 
+static void segregate_lowmem_region(int *nr_ranges, unsigned long lowmem_limit)
+{
+	unsigned long long end, start;
+	unsigned type;
+
+	start = crash_memory_range[*nr_ranges].start;
+	end = crash_memory_range[*nr_ranges].end;
+	type = crash_memory_range[*nr_ranges].type;
+
+	if (!(lowmem_limit && lowmem_limit > start && lowmem_limit < end))
+		return;
+
+	crash_memory_range[*nr_ranges].end = lowmem_limit - 1;
+
+	if (*nr_ranges >= CRASH_MAX_MEMORY_RANGES - 1)
+		return;
+
+	++*nr_ranges;
+
+	crash_memory_range[*nr_ranges].start = lowmem_limit;
+	crash_memory_range[*nr_ranges].end = end;
+	crash_memory_range[*nr_ranges].type = type;
+}
+
 /* Removes crash reserve region from list of memory chunks for whom elf program
  * headers have to be created. Assuming crash reserve region to be a single
  * continuous area fully contained inside one of the memory chunks */
-- 
1.5.6.5



From daniel.kiper at oracle.com  Mon Sep 10 07:57:51 2012
From: daniel.kiper at oracle.com (Daniel Kiper)
Date: Mon, 10 Sep 2012 13:57:51 +0200
Subject: [PATCH 7/7] xen: Fix Xen kdump support
In-Reply-To: <1347278271-5211-7-git-send-email-daniel.kiper@oracle.com>
References: <1347278271-5211-1-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-2-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-3-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-4-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-5-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-6-git-send-email-daniel.kiper@oracle.com>
 <1347278271-5211-7-git-send-email-daniel.kiper@oracle.com>
Message-ID: <1347278271-5211-8-git-send-email-daniel.kiper@oracle.com>

get_crash_memory_ranges() is unreliable under Xen. Proper machine
memory map could be obtained under Xen by calling __HYPERVISOR_memory_op
hypercall with XENMEM_machine_memory_map argument. get_crash_memory_ranges_xen()
does that. It is implemented using ioctl() or libxenctrl interface.
This solution is compatible with 3.x and 4.x Xen versions.

Signed-off-by: Daniel Kiper <daniel.kiper at oracle.com>
---
 kexec/arch/i386/crashdump-x86.c |  203 ++++++++++++++++++++++++++++++++++++---
 1 files changed, 191 insertions(+), 12 deletions(-)

diff --git a/kexec/arch/i386/crashdump-x86.c b/kexec/arch/i386/crashdump-x86.c
index c6b9354..09c3fd4 100644
--- a/kexec/arch/i386/crashdump-x86.c
+++ b/kexec/arch/i386/crashdump-x86.c
@@ -18,21 +18,41 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
+
+#define _XOPEN_SOURCE	600
+#define _BSD_SOURCE
+
+#include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <limits.h>
 #include <elf.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include "../../kexec.h"
 #include "../../kexec-elf.h"
 #include "../../kexec-syscall.h"
+#include "../../firmware_memmap.h"
 #include "../../crashdump.h"
 #include "kexec-x86.h"
 #include "crashdump-x86.h"
+
+#ifdef HAVE_LIBXENCTRL
+#ifdef HAVE_XC_GET_MACHINE_MEMORY_MAP
+#include <xenctrl.h>
+#else
+#define __XEN_TOOLS__	1
+#include <xen/xen.h>
+#include <xen/memory.h>
+#include <xen/sys/privcmd.h>
+#endif /* HAVE_XC_GET_MACHINE_MEMORY_MAP */
+#endif /* HAVE_LIBXENCTRL */
+
 #include <x86/x86-linux.h>
 
 extern struct arch_options_t arch_options;
@@ -273,6 +293,162 @@ static int get_crash_memory_ranges(struct memory_range **range, int *ranges,
 	return 0;
 }
 
+#ifdef HAVE_LIBXENCTRL
+#ifdef HAVE_XC_GET_MACHINE_MEMORY_MAP
+static int get_crash_memory_ranges_xen(struct memory_range **range,
+					int *ranges, unsigned long lowmem_limit)
+{
+	int j, rc, ret = -1;
+	struct e820entry e820entries[CRASH_MAX_MEMORY_RANGES];
+	unsigned int i;
+#ifdef XENCTRL_HAS_XC_INTERFACE
+	xc_interface *xc;
+#else
+	int xc;
+#endif
+
+#ifdef XENCTRL_HAS_XC_INTERFACE
+	xc = xc_interface_open(NULL, NULL, 0);
+
+	if (!xc) {
+		fprintf(stderr, "%s: Failed to open Xen control interface\n", __func__);
+		goto err;
+	}
+#else
+	xc = xc_interface_open();
+
+	if (xc == -1) {
+		fprintf(stderr, "%s: Failed to open Xen control interface\n", __func__);
+		goto err;
+	}
+#endif
+
+	rc = xc_get_machine_memory_map(xc, e820entries, CRASH_MAX_MEMORY_RANGES);
+
+	if (rc < 0) {
+		fprintf(stderr, "%s: xc_get_machine_memory_map: %s\n", __func__, strerror(-rc));
+		goto err;
+	}
+
+	for (i = 0, j = 0; i < rc && j < CRASH_MAX_MEMORY_RANGES; ++i, ++j) {
+		crash_memory_range[j].start = e820entries[i].addr;
+		crash_memory_range[j].end = e820entries[i].addr + e820entries[i].size - 1;
+		crash_memory_range[j].type = xen_e820_to_kexec_type(e820entries[i].type);
+		segregate_lowmem_region(&j, lowmem_limit);
+	}
+
+	*range = crash_memory_range;
+	*ranges = j;
+
+	qsort(*range, *ranges, sizeof(struct memory_range), compare_ranges);
+
+	if (exclude_region(ranges, crash_reserved_mem.start,
+						crash_reserved_mem.end) < 0)
+		goto err;
+
+	ret = 0;
+
+err:
+	xc_interface_close(xc);
+
+	return ret;
+}
+#else
+static int get_crash_memory_ranges_xen(struct memory_range **range,
+					int *ranges, unsigned long lowmem_limit)
+{
+	int fd, j, rc, ret = -1;
+	privcmd_hypercall_t hypercall;
+	struct e820entry *e820entries = NULL;
+	struct xen_memory_map *xen_memory_map = NULL;
+	unsigned int i;
+
+	fd = open("/proc/xen/privcmd", O_RDWR);
+
+	if (fd == -1) {
+		fprintf(stderr, "%s: open(/proc/xen/privcmd): %m\n", __func__);
+		goto err;
+	}
+
+	rc = posix_memalign((void **)&e820entries, getpagesize(),
+			    sizeof(struct e820entry) * CRASH_MAX_MEMORY_RANGES);
+
+	if (rc) {
+		fprintf(stderr, "%s: posix_memalign(e820entries): %s\n", __func__, strerror(rc));
+		e820entries = NULL;
+		goto err;
+	}
+
+	rc = posix_memalign((void **)&xen_memory_map, getpagesize(),
+			    sizeof(struct xen_memory_map));
+
+	if (rc) {
+		fprintf(stderr, "%s: posix_memalign(xen_memory_map): %s\n", __func__, strerror(rc));
+		xen_memory_map = NULL;
+		goto err;
+	}
+
+	if (mlock(e820entries, sizeof(struct e820entry) * CRASH_MAX_MEMORY_RANGES) == -1) {
+		fprintf(stderr, "%s: mlock(e820entries): %m\n", __func__);
+		goto err;
+	}
+
+	if (mlock(xen_memory_map, sizeof(struct xen_memory_map)) == -1) {
+		fprintf(stderr, "%s: mlock(xen_memory_map): %m\n", __func__);
+		goto err;
+	}
+
+	xen_memory_map->nr_entries = CRASH_MAX_MEMORY_RANGES;
+	set_xen_guest_handle(xen_memory_map->buffer, e820entries);
+
+	hypercall.op = __HYPERVISOR_memory_op;
+	hypercall.arg[0] = XENMEM_machine_memory_map;
+	hypercall.arg[1] = (__u64)xen_memory_map;
+
+	rc = ioctl(fd, IOCTL_PRIVCMD_HYPERCALL, &hypercall);
+
+	if (rc == -1) {
+		fprintf(stderr, "%s: ioctl(IOCTL_PRIVCMD_HYPERCALL): %m\n", __func__);
+		goto err;
+	}
+
+	for (i = 0, j = 0; i < xen_memory_map->nr_entries &&
+				j < CRASH_MAX_MEMORY_RANGES; ++i, ++j) {
+		crash_memory_range[j].start = e820entries[i].addr;
+		crash_memory_range[j].end = e820entries[i].addr + e820entries[i].size - 1;
+		crash_memory_range[j].type = xen_e820_to_kexec_type(e820entries[i].type);
+		segregate_lowmem_region(&j, lowmem_limit);
+	}
+
+	*range = crash_memory_range;
+	*ranges = j;
+
+	qsort(*range, *ranges, sizeof(struct memory_range), compare_ranges);
+
+	if (exclude_region(ranges, crash_reserved_mem.start,
+						crash_reserved_mem.end) < 0)
+		goto err;
+
+	ret = 0;
+
+err:
+	munlock(xen_memory_map, sizeof(struct xen_memory_map));
+	munlock(e820entries, sizeof(struct e820entry) * CRASH_MAX_MEMORY_RANGES);
+	free(xen_memory_map);
+	free(e820entries);
+	close(fd);
+
+	return ret;
+}
+#endif /* HAVE_XC_GET_MACHINE_MEMORY_MAP */
+#else
+static int get_crash_memory_ranges_xen(struct memory_range **range,
+					int *ranges, unsigned long lowmem_limit)
+{
+	return 0;
+}
+#endif /* HAVE_LIBXENCTRL */
+
 static void segregate_lowmem_region(int *nr_ranges, unsigned long lowmem_limit)
 {
 	unsigned long long end, start;
@@ -724,10 +900,15 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
 		return -1;
 	}
 
-	if (get_crash_memory_ranges(&mem_range, &nr_ranges,
-				    info->kexec_flags,
-				    elf_info.lowmem_limit) < 0)
-		return -1;
+	if (xen_present()) {
+		if (get_crash_memory_ranges_xen(&mem_range, &nr_ranges,
+						elf_info.lowmem_limit) < 0)
+			return -1;
+	} else
+		if (get_crash_memory_ranges(&mem_range, &nr_ranges,
+						info->kexec_flags,
+						elf_info.lowmem_limit) < 0)
+			return -1;
 
 	get_backup_area(info, mem_range, nr_ranges);
 
@@ -784,17 +965,15 @@ int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline,
 
 	/* Create elf header segment and store crash image data. */
 	if (arch_options.core_header_type == CORE_TYPE_ELF64) {
-		if (crash_create_elf64_headers(info, &elf_info,
-					       crash_memory_range, nr_ranges,
-					       &tmp, &bufsz,
-					       ELF_CORE_HEADER_ALIGN) < 0)
+		if (crash_create_elf64_headers(info, &elf_info, mem_range,
+						nr_ranges, &tmp, &bufsz,
+						ELF_CORE_HEADER_ALIGN) < 0)
 			return EFAILED;
 	}
 	else {
-		if (crash_create_elf32_headers(info, &elf_info,
-					       crash_memory_range, nr_ranges,
-					       &tmp, &bufsz,
-					       ELF_CORE_HEADER_ALIGN) < 0)
+		if (crash_create_elf32_headers(info, &elf_info, mem_range,
+						nr_ranges, &tmp, &bufsz,
+						ELF_CORE_HEADER_ALIGN) < 0)
 			return EFAILED;
 	}
 	/* the size of the elf headers allocated is returned in 'bufsz' */
-- 
1.5.6.5



From daniel.kiper at oracle.com  Mon Sep 10 08:06:31 2012
From: daniel.kiper at oracle.com (Daniel Kiper)
Date: Mon, 10 Sep 2012 05:06:31 -0700 (PDT)
Subject: [PATCH] kexec-tools: Read always one vmcoreinfo file
Message-ID: <6b55cbb0-bef3-4105-b99d-69d4a610a7a5@default>

Hi Petr,

[...]

> > > As I know Petr was going to do some tests.
> > > I have not received any reply from him till now.
> > > Maybe he is busy or on vacation.
> >
> > According to automatic reply he is on vacation until 13/08/2012.
>
> Thanks. I guess we should wait then.

Have you done some tests of this patch?
Did you find any issues with it?

Daniel


From vgoyal at redhat.com  Mon Sep 10 10:36:04 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Mon, 10 Sep 2012 10:36:04 -0400
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <50473306.1070803@jp.fujitsu.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com>
 <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com>
 <50473306.1070803@jp.fujitsu.com>
Message-ID: <20120910143604.GB639@redhat.com>

On Wed, Sep 05, 2012 at 08:09:58PM +0900, Takao Indoh wrote:
> (2012/08/07 5:39), Vivek Goyal wrote:
> >On Mon, Aug 06, 2012 at 01:30:47PM +0900, Takao Indoh wrote:
> >>Hi Vivek,
> >>
> >>(2012/08/03 20:46), Vivek Goyal wrote:
> >>>On Fri, Aug 03, 2012 at 08:24:31PM +0900, Takao Indoh wrote:
> >>>>Hi all,
> >>>>
> >>>>This patch adds kernel parameter "reset_pcie_devices" which resets PCIe
> >>>>devices at boot time to address DMA problem on kdump with iommu. When
> >>>>this parameter is specified, a hot reset is triggered on each PCIe root
> >>>>port and downstream port to reset its downstream endpoint.
> >>>
> >>>Hi Takao,
> >>>
> >>>Why not use existing "reset_devices" parameter instead of introducing
> >>>a new one?
> >>
> >>"reset_devices" is used for each driver to reset their own device, and
> >>this patch resets all devices forcibly, so I thought they were different
> >>things.
> >
> >Yes reset_devices currently is used for driver to reset its device. I
> >thought one could very well extend its reach to reset pci express devices
> >at bus level.
> >
> >Having them separate is not going to be much useful from kdump
> >perspective. We will end up passing both reset_devices and
> >reset_pcie_devices to second kernel whill lead to bus level reset as well
> >as device level reset.
> >
> >Ideal situation would be that somehow detect that bus level reset has been
> >done and skip device level reset (assuming bus level reset obviates the
> >need of device level reset, please correct me if that's not the case).
> >
> >After pcie reset, can we store the state in a variable and drivers can
> >use that variable to check if PCIe level reset was done or not. If yes,
> >skip device level reset (Assuming driver knows that device is on a
> >PCIe slot).
> >
> >In that case we will not have to introduce new kernel command line, and
> >also avoid double reset?
> I found a problem when testing my patch on some machines.
> 
> Originally there are two problems in kdump kernel when iommu is enabled;
> DMAR error and PCI SERR. I thought they are fixed by my patch, but I
> noticed that PCI SERR is still detected after applying the patch. It
> seems that something happens when Interrupt Remapping is initialized in
> kdump kernel.
> 
> Therefore resetting devices has to be done before enable_IR() is
> called. I have three ideas for it.
> 
>  (i) Resetting devices in 1st kernel(panic kernel)
>  We can reset devices before jumping into 2nd kernel. Of course it may
>  be dangerous to scan pci device tree and call PCI functions in panic'd
>  kernel. Beforehand we need to collect device information so that only
>  minimal code could run on panic.
> 
>  (ii) Resetting devices in purgatory
>  It seems to be be appropriate place to do this, but I'm not sure
>  where I can save/restore PCI config when resetting devices in
>  purgatory.
> 
>  (iii) Resetting devices in 2nd kernel(kdump kernel)
>  Important point is to do reset before enable_IR() is called as I wrote
>  above. I think I should add new function to do reset into
>  arch/x86/pci/early.c and call it in setup_arch like
>  early_dump_pci_devices() or early_quirks().

I would not claim that I understand hte PCI SERR issue. But whatever
resettings needs to happen, should happen early in second kernel.

Doing it in first kernel is not a good idea as it is crashed kernel and
we want to as little as possible.

Doing it in purgatory is not a good idea either as purgatory does not
konw anything about kernel as such. We don't want to bloat purgatory
with reset code and embedding the device knowledge there.

Keeping it in second kernel makes sense so that code remains with kernel
and can be maintained there.

Thanks
Vivek


From khalid.aziz at hp.com  Mon Sep 10 12:29:00 2012
From: khalid.aziz at hp.com (Khalid Aziz)
Date: Mon, 10 Sep 2012 10:29:00 -0600
Subject: Problem with kexec on i386, linux-3.5
In-Reply-To: <504D81EE.7070409@gmx.at>
References: <500EE046.2000705@gmx.at> <504A5927.2090605@hp.com>
 <504D81EE.7070409@gmx.at>
Message-ID: <1347294540.4393.23.camel@lyra>

On Mon, 2012-09-10 at 08:00 +0200, Christian Schaubschl?ger wrote:
> Hello Khalid,
> 
> > Are you not loading the driver for your disk drive controller when the 
> > new kernel boots up, even though you are not using the driver for disk 
> > I/O? If yes, the driver should have re-enabled Bus Master bit in its 
> > init routine. If you are loading the driver, which driver is it? I can 
> > take a look at it and see if there is anything missing in the 
> > initialization routine. Can you also include output from "lspci -v" from 
> > your machine?
> 
> I'm not loading any drivers in my new kernel, I'm just doing pure BIOS disk I/O using Int13 calls (the program I start using kexec I would not actually call a 'kernel', it's just a very tiny piece of software which does some disk I/O and output on the screen).
> 
> Attached you find the output of lspci -v
> 
> Best regards
> Christian
> 
> 

Hello Christian,

You have a rather esoteric use case. The patch that clears Bus Master
bit relies upon drivers reinitializing the controllers which includes
setting the Bus Master bit as well. Can you access PCI config space in
your program that you kexec? If yes, can you set the Bus Master bit in
your program? You have a pretty standard IDE controller there which does
have Bus Master capability.

Thanks
-- 
Khalid Aziz <khalid.aziz at hp.com>



From indou.takao at jp.fujitsu.com  Tue Sep 11 06:32:35 2012
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Tue, 11 Sep 2012 19:32:35 +0900
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <20120910143604.GB639@redhat.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com> <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com> <50473306.1070803@jp.fujitsu.com>
 <20120910143604.GB639@redhat.com>
Message-ID: <504F1343.7030607@jp.fujitsu.com>

(2012/09/10 23:36), Vivek Goyal wrote:
> On Wed, Sep 05, 2012 at 08:09:58PM +0900, Takao Indoh wrote:
>> (2012/08/07 5:39), Vivek Goyal wrote:
>>> On Mon, Aug 06, 2012 at 01:30:47PM +0900, Takao Indoh wrote:
>>>> Hi Vivek,
>>>>
>>>> (2012/08/03 20:46), Vivek Goyal wrote:
>>>>> On Fri, Aug 03, 2012 at 08:24:31PM +0900, Takao Indoh wrote:
>>>>>> Hi all,
>>>>>>
>>>>>> This patch adds kernel parameter "reset_pcie_devices" which resets PCIe
>>>>>> devices at boot time to address DMA problem on kdump with iommu. When
>>>>>> this parameter is specified, a hot reset is triggered on each PCIe root
>>>>>> port and downstream port to reset its downstream endpoint.
>>>>>
>>>>> Hi Takao,
>>>>>
>>>>> Why not use existing "reset_devices" parameter instead of introducing
>>>>> a new one?
>>>>
>>>> "reset_devices" is used for each driver to reset their own device, and
>>>> this patch resets all devices forcibly, so I thought they were different
>>>> things.
>>>
>>> Yes reset_devices currently is used for driver to reset its device. I
>>> thought one could very well extend its reach to reset pci express devices
>>> at bus level.
>>>
>>> Having them separate is not going to be much useful from kdump
>>> perspective. We will end up passing both reset_devices and
>>> reset_pcie_devices to second kernel whill lead to bus level reset as well
>>> as device level reset.
>>>
>>> Ideal situation would be that somehow detect that bus level reset has been
>>> done and skip device level reset (assuming bus level reset obviates the
>>> need of device level reset, please correct me if that's not the case).
>>>
>>> After pcie reset, can we store the state in a variable and drivers can
>>> use that variable to check if PCIe level reset was done or not. If yes,
>>> skip device level reset (Assuming driver knows that device is on a
>>> PCIe slot).
>>>
>>> In that case we will not have to introduce new kernel command line, and
>>> also avoid double reset?
>> I found a problem when testing my patch on some machines.
>>
>> Originally there are two problems in kdump kernel when iommu is enabled;
>> DMAR error and PCI SERR. I thought they are fixed by my patch, but I
>> noticed that PCI SERR is still detected after applying the patch. It
>> seems that something happens when Interrupt Remapping is initialized in
>> kdump kernel.
>>
>> Therefore resetting devices has to be done before enable_IR() is
>> called. I have three ideas for it.
>>
>>   (i) Resetting devices in 1st kernel(panic kernel)
>>   We can reset devices before jumping into 2nd kernel. Of course it may
>>   be dangerous to scan pci device tree and call PCI functions in panic'd
>>   kernel. Beforehand we need to collect device information so that only
>>   minimal code could run on panic.
>>
>>   (ii) Resetting devices in purgatory
>>   It seems to be be appropriate place to do this, but I'm not sure
>>   where I can save/restore PCI config when resetting devices in
>>   purgatory.
>>
>>   (iii) Resetting devices in 2nd kernel(kdump kernel)
>>   Important point is to do reset before enable_IR() is called as I wrote
>>   above. I think I should add new function to do reset into
>>   arch/x86/pci/early.c and call it in setup_arch like
>>   early_dump_pci_devices() or early_quirks().
>
> I would not claim that I understand hte PCI SERR issue. But whatever
> resettings needs to happen, should happen early in second kernel.
>
> Doing it in first kernel is not a good idea as it is crashed kernel and
> we want to as little as possible.
>
> Doing it in purgatory is not a good idea either as purgatory does not
> konw anything about kernel as such. We don't want to bloat purgatory
> with reset code and embedding the device knowledge there.
>
> Keeping it in second kernel makes sense so that code remains with kernel
> and can be maintained there.

I'll post new patch which clears bus master bit and resets devices in
second kernel.

As to the boot parameter to enable this function, you suggested using
reset_devices. I found that on a certain platform resetting devices
caused PCIe error due to a hardware bug. Therefore I think we need
new parameter apart from reset_devices to disable this function on
such a machine.

Thanks,
Takao Indoh



From kaneshige.kenji at jp.fujitsu.com  Tue Sep 11 07:52:42 2012
From: kaneshige.kenji at jp.fujitsu.com (Kaneshige, Kenji)
Date: Tue, 11 Sep 2012 11:52:42 +0000
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <504D8A28.9090105@jp.fujitsu.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com> <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com> <50473306.1070803@jp.fujitsu.com>
 <4A338DB2991D2A44B9A44B8718AECF650A4AA6BF@G01JPEXMBYT03>
 <504D8A28.9090105@jp.fujitsu.com>
Message-ID: <4A338DB2991D2A44B9A44B8718AECF650A4AC9A5@G01JPEXMBYT03>

> -----Original Message-----
> From: Takao Indoh [mailto:indou.takao at jp.fujitsu.com]
> Sent: Monday, September 10, 2012 3:35 PM
> To: Kaneshige, Kenji/?? ??
> Cc: vgoyal at redhat.com; kexec at lists.infradead.org;
> linux-kernel at vger.kernel.org; linux-pci at vger.kernel.org;
> bhelgaas at google.com; hbabu at us.ibm.com; Ishii, Hironobu/?? ??;
> martin.wilck at ts.fujitsu.com
> Subject: Re: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
> with iommu
> 
> (2012/09/10 11:34), Kaneshige, Kenji wrote:
> >> -----Original Message-----
> >> From: linux-pci-owner at vger.kernel.org
> >> [mailto:linux-pci-owner at vger.kernel.org] On Behalf Of Takao Indoh
> >> Sent: Wednesday, September 05, 2012 8:10 PM
> >> To: vgoyal at redhat.com
> >> Cc: kexec at lists.infradead.org; linux-kernel at vger.kernel.org;
> >> linux-pci at vger.kernel.org; bhelgaas at google.com; hbabu at us.ibm.com;
> Ishii,
> >> Hironobu/?? ??; martin.wilck at ts.fujitsu.com
> >> Subject: Re: [RFC][PATCH] Reset PCIe devices to address DMA problem on
> kdump
> >> with iommu
> >>
> >> (2012/08/07 5:39), Vivek Goyal wrote:
> >>> On Mon, Aug 06, 2012 at 01:30:47PM +0900, Takao Indoh wrote:
> >>>> Hi Vivek,
> >>>>
> >>>> (2012/08/03 20:46), Vivek Goyal wrote:
> >>>>> On Fri, Aug 03, 2012 at 08:24:31PM +0900, Takao Indoh wrote:
> >>>>>> Hi all,
> >>>>>>
> >>>>>> This patch adds kernel parameter "reset_pcie_devices" which resets
> >> PCIe
> >>>>>> devices at boot time to address DMA problem on kdump with iommu.
> When
> >>>>>> this parameter is specified, a hot reset is triggered on each PCIe
> >> root
> >>>>>> port and downstream port to reset its downstream endpoint.
> >>>>>
> >>>>> Hi Takao,
> >>>>>
> >>>>> Why not use existing "reset_devices" parameter instead of introducing
> >>>>> a new one?
> >>>>
> >>>> "reset_devices" is used for each driver to reset their own device,
> and
> >>>> this patch resets all devices forcibly, so I thought they were different
> >>>> things.
> >>>
> >>> Yes reset_devices currently is used for driver to reset its device.
> I
> >>> thought one could very well extend its reach to reset pci express devices
> >>> at bus level.
> >>>
> >>> Having them separate is not going to be much useful from kdump
> >>> perspective. We will end up passing both reset_devices and
> >>> reset_pcie_devices to second kernel whill lead to bus level reset as
> well
> >>> as device level reset.
> >>>
> >>> Ideal situation would be that somehow detect that bus level reset has
> >> been
> >>> done and skip device level reset (assuming bus level reset obviates
> the
> >>> need of device level reset, please correct me if that's not the case).
> >>>
> >>> After pcie reset, can we store the state in a variable and drivers can
> >>> use that variable to check if PCIe level reset was done or not. If yes,
> >>> skip device level reset (Assuming driver knows that device is on a
> >>> PCIe slot).
> >>>
> >>> In that case we will not have to introduce new kernel command line,
> and
> >>> also avoid double reset?
> >>
> >> I found a problem when testing my patch on some machines.
> >>
> >> Originally there are two problems in kdump kernel when iommu is enabled;
> >> DMAR error and PCI SERR. I thought they are fixed by my patch, but I
> >> noticed that PCI SERR is still detected after applying the patch. It
> >> seems that something happens when Interrupt Remapping is initialized
> in
> >> kdump kernel.
> >
> > I'm not sure, but I guess the PCI SERR might be caused as follows.
> >
> > - The 1st kernel enables interrupt remapping. The MSI(-X) address and
> >    data registers of PCI devices are programmed in remappable format.
> >
> > - At the beginning of 2nd kernel, interrupt remapping is still active.
> >    And then it is disabled by enable_IR() function for initialization.
> >
> > - PCI device generate an interrupt. At this moment, interrupt remapping
> >    is not enabled yet. On the other hand, MSI(-X) address and data of
> this
> >    interrupt is in remappable format because those are programmed by 1st
> >    kernel. I guess this might be a cause of PCI SERR.
> >
> > I guess clearing command register or disabling MSI before interrupt
> > remapping initialization in 2nd kernel might solve the PCI SERR problem.
> 
> Thank you for your comment. That makes sense.
> 
> Though I think clearing bus master bit is enough, do you think I need to
> clear
> all command register bit not only bus master?

I thought clearing bus master bit. But we might also need to set the
disable INTx bit.

It would not be needed if we can reset devices before interrupt remapping
initialization. I guess resetting devices before interrupt remapping
initialization would need complex code change and be difficult to implement.
If so, clearing bus master bit would be one of the alternative solution
against PCI SERR issue.

Regards,
Kenji Kaneshige



> 
> Thanks,
> Takao Indoh
> 
> 
> > Regards,
> > Kenji Kaneshige
> >
> >
> >>
> >> Therefore resetting devices has to be done before enable_IR() is
> >> called. I have three ideas for it.
> >>
> >>    (i) Resetting devices in 1st kernel(panic kernel)
> >>    We can reset devices before jumping into 2nd kernel. Of course it
> may
> >>    be dangerous to scan pci device tree and call PCI functions in panic'd
> >>    kernel. Beforehand we need to collect device information so that only
> >>    minimal code could run on panic.
> >>
> >>    (ii) Resetting devices in purgatory
> >>    It seems to be be appropriate place to do this, but I'm not sure
> >>    where I can save/restore PCI config when resetting devices in
> >>    purgatory.
> >>
> >>    (iii) Resetting devices in 2nd kernel(kdump kernel)
> >>    Important point is to do reset before enable_IR() is called as I wrote
> >>    above. I think I should add new function to do reset into
> >>    arch/x86/pci/early.c and call it in setup_arch like
> >>    early_dump_pci_devices() or early_quirks().
> >>
> >> Any comments?
> >>
> >> Thanks,
> >> Takao Indoh
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-pci"
> in
> >> the body of a message to majordomo at vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >
> >



From vgoyal at redhat.com  Tue Sep 11 10:43:23 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Tue, 11 Sep 2012 10:43:23 -0400
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <504F1343.7030607@jp.fujitsu.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com>
 <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com>
 <50473306.1070803@jp.fujitsu.com> <20120910143604.GB639@redhat.com>
 <504F1343.7030607@jp.fujitsu.com>
Message-ID: <20120911144323.GF12039@redhat.com>

On Tue, Sep 11, 2012 at 07:32:35PM +0900, Takao Indoh wrote:

[..]
> I'll post new patch which clears bus master bit and resets devices in
> second kernel.
> 
> As to the boot parameter to enable this function, you suggested using
> reset_devices. I found that on a certain platform resetting devices
> caused PCIe error due to a hardware bug. Therefore I think we need
> new parameter apart from reset_devices to disable this function on
> such a machine.

Can you explain a bit more how the error happens. I still don't think
that because of a bug in a platform somewhere we should be introducing
a separate command line parameter and not reuse the exisiting one. Also
you have not explained what's the bug and how a new parameter will 
avoid the bug.

Thanks
Vivek


From horms at verge.net.au  Tue Sep 11 20:37:20 2012
From: horms at verge.net.au (Simon Horman)
Date: Wed, 12 Sep 2012 09:37:20 +0900
Subject: [PATCH 0/7] Add device-tree support to kexec-tools for ARM
In-Reply-To: <20120910085358.GA21650@mudshark.cambridge.arm.com>
References: <1347009086-16506-1-git-send-email-matthew.leach@arm.com>
 <20120910000550.GI30480@verge.net.au>
 <20120910085358.GA21650@mudshark.cambridge.arm.com>
Message-ID: <20120912003720.GE26818@verge.net.au>

On Mon, Sep 10, 2012 at 09:53:58AM +0100, Will Deacon wrote:
> On Mon, Sep 10, 2012 at 01:05:50AM +0100, Simon Horman wrote:
> > On Fri, Sep 07, 2012 at 10:11:19AM +0100, Matthew Leach wrote:
> > > Hi all,
> > > 
> > > Running a kexec() on ARM platforms has become an issue as information
> > > about the platform that is presented via device-tree is required to
> > > boot newer kernels.
> > > 
> > > The ATAGs kernel code is re-used, replacing the ATAGs with a
> > > device-tree blob so that only kexec-tools needs to be changed. There
> > > are two options for generating a dtb to be passed to the kernel from
> > > kexec-tools: 1) Read in the device-tree that is exposed in
> > > /proc/device-tree and flatten this out into a dtb.  2) Allow the user
> > > to specify a dtb file on the command line.  These blobs are then
> > > loaded into memory before the kernel image and the address passed
> > > through to r2, as stated in the ARM booting documentation.
> > > 
> > > These patches depend upon a kernel patch, namely:
> > > http://lists.infradead.org/pipermail/linux-arm-kernel/2012-September/118275.html
> > > 
> > > Simon - you are welcome to add your signed-off-by to my final patch as
> > > I incorporated bits of your final patch into mine.
> > 
> > Sure, I'll add the sign-off as part of merging the changes.
> > 
> > What I have in mind is to to merge the non ppc64/powerpc patches,
> > that is 5 of the 7 patches. I'm a but unsure how the kernel-side of things
> > will pan out, but an incremental patch can be made to kexec-tools
> > if needed and this series shouldn't break any existing support
> > Does that work for you?
> 
> Sounds good to me, I'll pursue the kernel-side changes for ARM.

Thanks. I have pushed the following kexec-tools patches.

* ARM: Add device tree support to the ARM platform
* arm: Make use of memory_ranges
* libfdt: Move from kexec/arch/ppc/libfdt/ to kexec/libfdt/
* kexec-elf.h: Include headers for types used
* fs2dt: Add a generic copy of fs2dt


From dyoung at redhat.com  Tue Sep 11 22:35:07 2012
From: dyoung at redhat.com (Dave Young)
Date: Wed, 12 Sep 2012 10:35:07 +0800
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <5049B6AD.9000304@redhat.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <5047DBA9.8030000@hp.com> <504815EB.9000701@redhat.com>
 <5048E40E.7040003@hp.com> <5049B6AD.9000304@redhat.com>
Message-ID: <504FF4DB.6030601@redhat.com>

On 09/07/2012 04:56 PM, Dave Young wrote:
> 
> I did some digging about the efi boot kdump in slackware with kernel
> from latest linus tree. I'm surprise that kdump works even without these
> "noefi" and "acpi_rsdp="
> 
> With fedora 17 3.4.3 kernel passing "acpi_rsdp=" is enough for kdump
> kernel booting.
> 
> Actually in x86 setup code if bootloader do not pass correct efi_info in
> boot_params efi_enabled will be set to 0 automaticlly.
> 
> So as for this patch 'noefi' is not needed.
> 
> I will do more testing to see why linus tree works without "acpi_rsdp="
> 

There's probably some efi changes between 3.4.3 - 3.6.0-rc4 cause this
works. I have not got time to bisect it.

Because it works without explicitly passing the kernel param, I will not
update the patch anymore.

Thanks everyone for your comments.


-- 
Thanks
Dave


From indou.takao at jp.fujitsu.com  Wed Sep 12 05:00:55 2012
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Wed, 12 Sep 2012 18:00:55 +0900
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <20120911144323.GF12039@redhat.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com> <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com> <50473306.1070803@jp.fujitsu.com>
 <20120910143604.GB639@redhat.com> <504F1343.7030607@jp.fujitsu.com>
 <20120911144323.GF12039@redhat.com>
Message-ID: <50504F47.80909@jp.fujitsu.com>

(2012/09/11 23:43), Vivek Goyal wrote:
> On Tue, Sep 11, 2012 at 07:32:35PM +0900, Takao Indoh wrote:
>
> [..]
>> I'll post new patch which clears bus master bit and resets devices in
>> second kernel.
>>
>> As to the boot parameter to enable this function, you suggested using
>> reset_devices. I found that on a certain platform resetting devices
>> caused PCIe error due to a hardware bug. Therefore I think we need
>> new parameter apart from reset_devices to disable this function on
>> such a machine.
>
> Can you explain a bit more how the error happens. I still don't think
> that because of a bug in a platform somewhere we should be introducing
> a separate command line parameter and not reuse the exisiting one. Also
> you have not explained what's the bug and how a new parameter will
> avoid the bug.

The bug I mentioned is that ACS Violation occurs at PCIe switch when
reading PCI configuration after device reset. I got information that
this violation is caused by PCIe switch bug. The machine becomes fatal
status by this error.

The reason why I try to introduce new parameter is that I want to avoid
regression by this patch. Let's say this patch was included in kernel
and its reset function was enabled by reset_devices as you said. AFAIK
reset_devices is always needed for kdump, so it means that devices are
always reset at kdump boot time. It causes a regression that system
always becomes abnormal status when we run kdump on the machine which has
a bug I mentioned.

To avoid this regression, I want to separate reset_devices from this
reset function. Or how about this?
- if user specify reset_devices, devices are reset by this patch, as you
   said.
- To avoid a regression I said, add new parameter like "pci=noreset".
   If this parameter is specified, the reset function I add is disabled
   and we can avoid regression.

Thanks,
Takao Indoh



From norbert.trapp at ts.fujitsu.com  Wed Sep 12 10:39:49 2012
From: norbert.trapp at ts.fujitsu.com (Trapp, Norbert)
Date: Wed, 12 Sep 2012 16:39:49 +0200
Subject: [PATCHv3 0/9] Support Xen versions up to xen-4.1
In-Reply-To: <20120903140100.ac4dbf21401ace0e24a442d9@mxc.nes.nec.co.jp>
References: <201208241741.27573.petr@tesarici.cz>
 <0E9227E8EFCFF54EA493F6C0399C015D39BFC5A112@ABGEX70E.FSC.NET>
 <20120903140100.ac4dbf21401ace0e24a442d9@mxc.nes.nec.co.jp>
Message-ID: <0E9227E8EFCFF54EA493F6C0399C015D39C0F0F687@ABGEX70E.FSC.NET>

Hello Atsushi, Petr, Stefan et al.,

When applying the makedumpfile Xen4 patches to the makedumpfile 1.5.0
version and using it for a crash file to save just the dom0 and xen pages
it again worked splendid in that makedumpfile was much faster than without
the Xen4 patches. Alas I had to remove the OFFSET_IN_UNION_INIT(page._domain,
"page_info", "domain") call because OFFSET_IN_UNION_INIT was no longer present.
It didn't matter much because the call is only needed for makedumpfile -g or when
using the /boot/xen-syms file. In the current 1.5.0  makedumpfile.c version you
see

    OFFSET_INIT(page_info._domain, "page_info", "u").

The Xen4 patch modified this because the _domain structure member is in different
unions for different version (x86, ia64) and may also not be the first entry in
the union depending on the Xen version.

    OFFSET_IN_UNION_INIT(page_info._domain, "page_info", "_domain");

As an experiment I tried to use

    OFFSET_INIT(page_info._domain, "page_info", "domain")

with makedumpfile 1.5.0. To get the correct offset I had to
modify the dwarf_info.c code:

--- ../makedumpfile-1.5.0/dwarf_info.c  2012-09-06 07:30:23.000000000 +0200
+++ dwarf_info.c        2012-09-12 15:49:23.000000000 +0200
@@ -449,8 +449,8 @@
 static int
 is_anonymous_container(Dwarf_Die *die)
 {
-       if (dwarf_diename(die))
-               return FALSE;
+       //if (dwarf_diename(die))
+       //      return FALSE;
        if (dwarf_tag(die) == DW_TAG_structure_type)
                return TRUE;
        if (dwarf_info.cmd != DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION
@@ -495,7 +495,7 @@
                 * Descend into anonymous members and search for member
                 * there.
                 */
-               if (!name) {
+               if ((!name) || (strcmp(name, dwarf_info.member_name) != 0)) {
                        if (!get_die_type(walker, &die_type))
                                continue;
                        if (is_anonymous_container(&die_type))


This is not a patch but just a description of what I modified for a test.
The underlying question is why only the anonymous unions are used and not the
ones with a name.

With kind regards

	Norbert

Norbert Trapp
PDG ES&S SWE OS 6

FUJITSU
Fujitsu Technology Solutions GmbH
Domagkstra?e 28, D-80807 M?nchen, Germany
E-mail: Norbert.Trapp at ts.fujitsu.com
Web: ts.fujitsu.com
Company details: ts.fujitsu.com/imprint

> -----Original Message-----
> From: Atsushi Kumagai [mailto:kumagai-atsushi at mxc.nes.nec.co.jp]
> Sent: Monday, September 03, 2012 7:01 AM
> To: Trapp, Norbert; petr at tesarici.cz
> Cc: kexec at lists.infradead.org
> Subject: Re: [PATCHv3 0/9] Support Xen versions up to xen-4.1
> 
...
> 
> Thank you for your report, that's good.
> So, I'll review these patches for makedumpfile-1.5.1.
> 
> 
> Thanks
> Atsushi Kumagai


From vgoyal at redhat.com  Thu Sep 13 09:38:27 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Thu, 13 Sep 2012 09:38:27 -0400
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <1347028634.20255.79.camel@lyra>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <5047DBA9.8030000@hp.com> <504815EB.9000701@redhat.com>
 <5048E40E.7040003@hp.com> <5049B6AD.9000304@redhat.com>
 <1347028634.20255.79.camel@lyra>
Message-ID: <20120913133827.GB4396@redhat.com>

On Fri, Sep 07, 2012 at 08:37:14AM -0600, Khalid Aziz wrote:
> On Fri, 2012-09-07 at 16:56 +0800, Dave Young wrote:
> > Actually in x86 setup code if bootloader do not pass correct efi_info in
> > boot_params efi_enabled will be set to 0 automaticlly.
> > 
> 
> When we kexec a kernel, the EFI signature is missing in the bootloader
> signature in boot_params, so kexec'd kernels currently disable EFI
> automatically even without noefi in this code:
> 
> arch/x86/kernel/setup.c:
> 
> 733         if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
> 734                      "EL32", 4)) {
> 735                 efi_enabled = 1;
> 736                 efi_64bit = false;
> 737         } else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signatu     re,             
> 738                      "EL64", 4)) {
> 739                 efi_enabled = 1;
> 740                 efi_64bit = true;
> 741         }
> 
> efi_enabled is initialized to 0.

Hi Khalid,

So what does this mean? Second kernel assumes the regular BIOS and tries
to initialize that way? That sounds broken or is it just fine given
the fact we are anyway not planning to call into any of the efi services.
But what about memory maps, ACPI tables etc.

Thanks
Vivek


From vgoyal at redhat.com  Thu Sep 13 10:10:18 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Thu, 13 Sep 2012 10:10:18 -0400
Subject: Query about cyclic buffer size
Message-ID: <20120913141018.GG4396@redhat.com>

Hi Atsushi-san,

How is size of cyclic buffer decided with 1.5.0? In practice I don't think
asking user for the size is a good idea as user does not know how much
memory will be left after kernel boot.

Will it make sense for makedumpfile to automatically determine the buffer
size based on amount of free memory available in the system. Something
like use 70-80% of free memory as cyclic buffer.

Thanks
Vivek



From horms at verge.net.au  Thu Sep 13 23:30:59 2012
From: horms at verge.net.au (Simon Horman)
Date: Fri, 14 Sep 2012 12:30:59 +0900
Subject: [PATCH 0/7] kdump: Xen fixes
In-Reply-To: <1347278271-5211-1-git-send-email-daniel.kiper@oracle.com>
References: <1347278271-5211-1-git-send-email-daniel.kiper@oracle.com>
Message-ID: <20120914033059.GF17943@verge.net.au>

On Mon, Sep 10, 2012 at 01:57:44PM +0200, Daniel Kiper wrote:
> Hi,
> 
> Here I am sending Xen kdump fixes.

Hi Daniel,

do these relate to the changes that you were discussing
with Petr Tesarik in July?


> Daniel Kiper (7):
>       kexec: Define some constants and structures conditionally
>       xen: Rename e820_to_kexec_type() to xen_e820_to_kexec_type() and export it
>       kexec: Move crash kernel area placement and size detection to is_crashkernel_mem_reserved()
>       kexec: Add segregate_lowmem_region()
>       kexec: Get backup area start address and size directly from mem_range
>       kexec: Move crash memory ranges logging
>       xen: Fix Xen kdump support
> 
>  include/x86/x86-linux.h            |    7 +-
>  kexec/arch/i386/crashdump-x86.c    |  322 +++++++++++++++++++++++++++--------
>  kexec/arch/i386/kexec-x86-common.c |    6 +-
>  kexec/arch/i386/kexec-x86.h        |    2 +
>  4 files changed, 259 insertions(+), 78 deletions(-)
> 
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec
> 


From daniel.kiper at oracle.com  Fri Sep 14 09:01:53 2012
From: daniel.kiper at oracle.com (Daniel Kiper)
Date: Fri, 14 Sep 2012 06:01:53 -0700 (PDT)
Subject: [PATCH 0/7] kdump: Xen fixes
Message-ID: <ff6ec2d4-fe0b-4c2e-8547-567e887355d3@default>

Hi Simon,

> do these relate to the changes that you were discussing
> with Petr Tesarik in July?

No. They are independent of vmcoreinfo patch.

Daniel


From vgoyal at redhat.com  Fri Sep 14 11:48:18 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Fri, 14 Sep 2012 11:48:18 -0400
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <50504F47.80909@jp.fujitsu.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com>
 <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com>
 <50473306.1070803@jp.fujitsu.com> <20120910143604.GB639@redhat.com>
 <504F1343.7030607@jp.fujitsu.com>
 <20120911144323.GF12039@redhat.com> <50504F47.80909@jp.fujitsu.com>
Message-ID: <20120914154817.GE6221@redhat.com>

On Wed, Sep 12, 2012 at 06:00:55PM +0900, Takao Indoh wrote:
> (2012/09/11 23:43), Vivek Goyal wrote:
> >On Tue, Sep 11, 2012 at 07:32:35PM +0900, Takao Indoh wrote:
> >
> >[..]
> >>I'll post new patch which clears bus master bit and resets devices in
> >>second kernel.
> >>
> >>As to the boot parameter to enable this function, you suggested using
> >>reset_devices. I found that on a certain platform resetting devices
> >>caused PCIe error due to a hardware bug. Therefore I think we need
> >>new parameter apart from reset_devices to disable this function on
> >>such a machine.
> >
> >Can you explain a bit more how the error happens. I still don't think
> >that because of a bug in a platform somewhere we should be introducing
> >a separate command line parameter and not reuse the exisiting one. Also
> >you have not explained what's the bug and how a new parameter will
> >avoid the bug.
> 
> The bug I mentioned is that ACS Violation occurs at PCIe switch when
> reading PCI configuration after device reset. I got information that
> this violation is caused by PCIe switch bug. The machine becomes fatal
> status by this error.
> 
> The reason why I try to introduce new parameter is that I want to avoid
> regression by this patch. Let's say this patch was included in kernel
> and its reset function was enabled by reset_devices as you said. AFAIK
> reset_devices is always needed for kdump, so it means that devices are
> always reset at kdump boot time. It causes a regression that system
> always becomes abnormal status when we run kdump on the machine which has
> a bug I mentioned.
> 
> To avoid this regression, I want to separate reset_devices from this
> reset function. Or how about this?
> - if user specify reset_devices, devices are reset by this patch, as you
>   said.
> - To avoid a regression I said, add new parameter like "pci=noreset".
>   If this parameter is specified, the reset function I add is disabled
>   and we can avoid regression.

Can we identify that particular switch in code and not reset it in code.
Introducing new paramenters to avoid bugs really feels odd.

Also, what was the conclusion to avoid double reset. I am assuming that
we don't want to do bus level reset as well as driver level reset based
on reset_devices. 

Thanks
Vivek


From konrad at kernel.org  Fri Sep 14 16:03:36 2012
From: konrad at kernel.org (Konrad Rzeszutek Wilk)
Date: Fri, 14 Sep 2012 16:03:36 -0400
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <504F1343.7030607@jp.fujitsu.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com>
 <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com>
 <50473306.1070803@jp.fujitsu.com> <20120910143604.GB639@redhat.com>
 <504F1343.7030607@jp.fujitsu.com>
Message-ID: <20120914200334.GA9041@phenom.dumpdata.com>

> As to the boot parameter to enable this function, you suggested using
> reset_devices. I found that on a certain platform resetting devices
> caused PCIe error due to a hardware bug. Therefore I think we need
> new parameter apart from reset_devices to disable this function on
> such a machine.

Wouldn't a DMI quirk be better for this? That way the second kernel
internally would know not to do this.


From khalid.aziz at hp.com  Fri Sep 14 16:32:31 2012
From: khalid.aziz at hp.com (Khalid Aziz)
Date: Fri, 14 Sep 2012 14:32:31 -0600
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <20120913133827.GB4396@redhat.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <5047DBA9.8030000@hp.com> <504815EB.9000701@redhat.com>
 <5048E40E.7040003@hp.com> <5049B6AD.9000304@redhat.com>
 <1347028634.20255.79.camel@lyra> <20120913133827.GB4396@redhat.com>
Message-ID: <5053945F.9060107@hp.com>

On 09/13/2012 07:38 AM, Vivek Goyal wrote:
> So what does this mean? Second kernel assumes the regular BIOS and tries
> to initialize that way? That sounds broken or is it just fine given
> the fact we are anyway not planning to call into any of the efi services.
> But what about memory maps, ACPI tables etc.

Hi Vivek,

My understanding on x86 side is not as clear as on ia64 side of kexec. 
 From my reading of the code, second kernel seems to assume a regular 
BIOS. It searches through EBDA or upper memory region E0000h-FFFFFh to 
find RSDP, if an RSDP pointer was not passed to the second kernel. This 
works on my EFI machine which also implements a BIOS compatibility 
layer. I wonder how it works on pure EFI machines. Do pure EFI machines 
not implement, say EBDA? If yes, acpi_find_root_pointer() should fail 
tofind RSDP.As for memory map, all I can find are reference to e820 
memory map which again assumes a BIOS but most EFI implementations I 
have come across implement a BIOS compatibility layer, so this will work 
still. I will look some more into this.

--
Khalid


From norbert.trapp at ts.fujitsu.com  Mon Sep 17 12:52:57 2012
From: norbert.trapp at ts.fujitsu.com (Trapp, Norbert)
Date: Mon, 17 Sep 2012 18:52:57 +0200
Subject: [PATCHv3 0/9] Support Xen versions up to xen-4.1
In-Reply-To: <505719BD.6080608@canonical.com>
References: <201208241741.27573.petr@tesarici.cz>
 <0E9227E8EFCFF54EA493F6C0399C015D39BFC5A112@ABGEX70E.FSC.NET>
 <20120903140100.ac4dbf21401ace0e24a442d9@mxc.nes.nec.co.jp>
 <0E9227E8EFCFF54EA493F6C0399C015D39C0F0F687@ABGEX70E.FSC.NET>
 <505719BD.6080608@canonical.com>
Message-ID: <0E9227E8EFCFF54EA493F6C0399C015D39C1018D5B@ABGEX70E.FSC.NET>

Hello Stefan,

> -----Original Message-----
> From: Stefan Bader [mailto:stefan.bader at canonical.com]
> Sent: Monday, September 17, 2012 2:38 PM
> To: Trapp, Norbert
> Cc: Atsushi Kumagai; petr at tesarici.cz; kexec at lists.infradead.org
> Subject: Re: [PATCHv3 0/9] Support Xen versions up to xen-4.1
> 
> On 12.09.2012 16:39, Trapp, Norbert wrote:
> > Hello Atsushi, Petr, Stefan et al.,
> >
> 
> Hi Norbert,
> 
> > When applying the makedumpfile Xen4 patches to the makedumpfile 1.5.0
> > version and using it for a crash file to save just the dom0 and xen pages
> > it again worked splendid in that makedumpfile was much faster than without
> > the Xen4 patches. Alas I had to remove the OFFSET_IN_UNION_INIT(page._domain,
> > "page_info", "domain") call because OFFSET_IN_UNION_INIT was no longer present.
> > It didn't matter much because the call is only needed for makedumpfile -g or when
> > using the /boot/xen-syms file. In the current 1.5.0  makedumpfile.c version you
> > see
> >
> >     OFFSET_INIT(page_info._domain, "page_info", "u").
> >
> > The Xen4 patch modified this because the _domain structure member is in different
> > unions for different version (x86, ia64) and may also not be the first entry in
> > the union depending on the Xen version.
> >
> >     OFFSET_IN_UNION_INIT(page_info._domain, "page_info", "_domain");
> >
> > As an experiment I tried to use
> >
> 
> >     OFFSET_INIT(page_info._domain, "page_info", "domain")
> 
> Just to make sure and since I am a bit lazy: with the Xen patch the page_info
> structure has a member (somewhere) named domain? (or _domain)?
> 

Just to get you on the right track, the struct page_info in the Xen code is meant.
Not the one in the makedumpfile code.

For example in xen-4.1.3/xen/common/kexec.c:
#ifdef __ia64__
    VMCOREINFO_OFFSET_SUB(page_info, u.inuse, _domain);
#else
    VMCOREINFO_OFFSET_SUB(page_info, v.inuse, _domain);
#endif

And the different page_info structures you find in:
xen-4.1.3/xen/include/asm-ia64/mm.h
xen-4.1.3/xen/include/asm-x86/mm.h

And also the structures can be different depending on the Xen version.

> >
> > with makedumpfile 1.5.0. To get the correct offset I had to
> > modify the dwarf_info.c code:
> >
> > --- ../makedumpfile-1.5.0/dwarf_info.c  2012-09-06 07:30:23.000000000 +0200
> > +++ dwarf_info.c        2012-09-12 15:49:23.000000000 +0200
> > @@ -449,8 +449,8 @@
> >  static int
> >  is_anonymous_container(Dwarf_Die *die)
> >  {
> > -       if (dwarf_diename(die))
> > -               return FALSE;
> > +       //if (dwarf_diename(die))
> > +       //      return FALSE;
> >         if (dwarf_tag(die) == DW_TAG_structure_type)
> >                 return TRUE;
> >         if (dwarf_info.cmd != DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION
> > @@ -495,7 +495,7 @@
> >                  * Descend into anonymous members and search for member
> >                  * there.
> >                  */
> > -               if (!name) {
> > +               if ((!name) || (strcmp(name, dwarf_info.member_name) != 0)) {
> >                         if (!get_die_type(walker, &die_type))
> >                                 continue;
> >                         if (is_anonymous_container(&die_type))
> >
> >
> > This is not a patch but just a description of what I modified for a test.
> > The underlying question is why only the anonymous unions are used and not the
> > ones with a name.
> 
> I made the patch because one element in some anonymous structure/union combo was
> not found in newer kernels and the previous exceptions for such a thing were
> hard coded. But as far as the dwarf info I was looking at the named
> structures/unions were handled and I did not want to modify that case without a
> way to test.
> 
> -Stefan

With kind regards

	Norbert

Norbert Trapp
PBG PDG ES&S SWE OS 6

FUJITSU
Fujitsu Technology Solutions GmbH
Domagkstra?e 28, D-80807 M?nchen, Germany
E-mail: Norbert.Trapp at ts.fujitsu.com
Web: ts.fujitsu.com
Company details: ts.fujitsu.com/imprint



From bhelgaas at google.com  Mon Sep 17 16:54:16 2012
From: bhelgaas at google.com (Bjorn Helgaas)
Date: Mon, 17 Sep 2012 14:54:16 -0600
Subject: [RFC 1/3] PCI/PM: Fix kexec for D3cold and bridge suspending
In-Reply-To: <1347872076-5260-2-git-send-email-ying.huang@intel.com>
References: <1347872076-5260-1-git-send-email-ying.huang@intel.com>
 <1347872076-5260-2-git-send-email-ying.huang@intel.com>
Message-ID: <CAErSpo5fVbN2vD5Omc7dGJFWUccYZoCOVRF4YmXPe2Oxm81u5g@mail.gmail.com>

+cc Eric and kexec list

On Mon, Sep 17, 2012 at 2:54 AM, Huang Ying <ying.huang at intel.com> wrote:
> If PCI devices are put into D3cold before kexec, because the
> configuration registers of PCI devices in D3cold are not accessible.
>
> And if PCI bridges are put into low power state before kexec,
> configuration registers of PCI devices underneath the PCI bridges are
> not accessible too.
>
> These will make some PCI devices can not be scanned after kexec, so
> resume the PCI devices in D3cold or PCI bridges in low power state
> before kexec.

Don't we need to resume the device even without the kexec issue?  And
even if it's in D1 or D2?

It looks to me like pci_msi_shutdown() (and probably drv->shutdown())
depend on the device being in D0.

> Signed-off-by: Huang Ying <ying.huang at intel.com>
> ---
>  drivers/pci/pci-driver.c |    4 ++++
>  1 file changed, 4 insertions(+)
>
> --- a/drivers/pci/pci-driver.c
> +++ b/drivers/pci/pci-driver.c
> @@ -421,6 +421,10 @@ static void pci_device_shutdown(struct d
>         struct pci_dev *pci_dev = to_pci_dev(dev);
>         struct pci_driver *drv = pci_dev->driver;
>
> +       /* Resume bridges and devices in D3cold for kexec to work properly */
> +       if (pci_dev->current_state == PCI_D3cold || pci_dev->subordinate)
> +               pm_runtime_resume(dev);
> +
>         if (drv && drv->shutdown)
>                 drv->shutdown(pci_dev);
>         pci_msi_shutdown(pci_dev);


From stefan.bader at canonical.com  Mon Sep 17 08:38:21 2012
From: stefan.bader at canonical.com (Stefan Bader)
Date: Mon, 17 Sep 2012 14:38:21 +0200
Subject: [PATCHv3 0/9] Support Xen versions up to xen-4.1
In-Reply-To: <0E9227E8EFCFF54EA493F6C0399C015D39C0F0F687@ABGEX70E.FSC.NET>
References: <201208241741.27573.petr@tesarici.cz>
 <0E9227E8EFCFF54EA493F6C0399C015D39BFC5A112@ABGEX70E.FSC.NET>
 <20120903140100.ac4dbf21401ace0e24a442d9@mxc.nes.nec.co.jp>
 <0E9227E8EFCFF54EA493F6C0399C015D39C0F0F687@ABGEX70E.FSC.NET>
Message-ID: <505719BD.6080608@canonical.com>

On 12.09.2012 16:39, Trapp, Norbert wrote:
> Hello Atsushi, Petr, Stefan et al.,
> 

Hi Norbert,

> When applying the makedumpfile Xen4 patches to the makedumpfile 1.5.0
> version and using it for a crash file to save just the dom0 and xen pages
> it again worked splendid in that makedumpfile was much faster than without
> the Xen4 patches. Alas I had to remove the OFFSET_IN_UNION_INIT(page._domain,
> "page_info", "domain") call because OFFSET_IN_UNION_INIT was no longer present.
> It didn't matter much because the call is only needed for makedumpfile -g or when
> using the /boot/xen-syms file. In the current 1.5.0  makedumpfile.c version you
> see
> 
>     OFFSET_INIT(page_info._domain, "page_info", "u").
> 
> The Xen4 patch modified this because the _domain structure member is in different
> unions for different version (x86, ia64) and may also not be the first entry in
> the union depending on the Xen version.
> 
>     OFFSET_IN_UNION_INIT(page_info._domain, "page_info", "_domain");
> 
> As an experiment I tried to use
> 

>     OFFSET_INIT(page_info._domain, "page_info", "domain")

Just to make sure and since I am a bit lazy: with the Xen patch the page_info
structure has a member (somewhere) named domain? (or _domain)?

> 
> with makedumpfile 1.5.0. To get the correct offset I had to
> modify the dwarf_info.c code:
> 
> --- ../makedumpfile-1.5.0/dwarf_info.c  2012-09-06 07:30:23.000000000 +0200
> +++ dwarf_info.c        2012-09-12 15:49:23.000000000 +0200
> @@ -449,8 +449,8 @@
>  static int
>  is_anonymous_container(Dwarf_Die *die)
>  {
> -       if (dwarf_diename(die))
> -               return FALSE;
> +       //if (dwarf_diename(die))
> +       //      return FALSE;
>         if (dwarf_tag(die) == DW_TAG_structure_type)
>                 return TRUE;
>         if (dwarf_info.cmd != DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION
> @@ -495,7 +495,7 @@
>                  * Descend into anonymous members and search for member
>                  * there.
>                  */
> -               if (!name) {
> +               if ((!name) || (strcmp(name, dwarf_info.member_name) != 0)) {
>                         if (!get_die_type(walker, &die_type))
>                                 continue;
>                         if (is_anonymous_container(&die_type))
> 
> 
> This is not a patch but just a description of what I modified for a test.
> The underlying question is why only the anonymous unions are used and not the
> ones with a name.

I made the patch because one element in some anonymous structure/union combo was
not found in newer kernels and the previous exceptions for such a thing were
hard coded. But as far as the dwarf info I was looking at the named
structures/unions were handled and I did not want to modify that case without a
way to test.

-Stefan
> 
> With kind regards
> 
> 	Norbert
> 
> Norbert Trapp
> PDG ES&S SWE OS 6
> 
> FUJITSU
> Fujitsu Technology Solutions GmbH
> Domagkstra?e 28, D-80807 M?nchen, Germany
> E-mail: Norbert.Trapp at ts.fujitsu.com
> Web: ts.fujitsu.com
> Company details: ts.fujitsu.com/imprint
> 
>> -----Original Message-----
>> From: Atsushi Kumagai [mailto:kumagai-atsushi at mxc.nes.nec.co.jp]
>> Sent: Monday, September 03, 2012 7:01 AM
>> To: Trapp, Norbert; petr at tesarici.cz
>> Cc: kexec at lists.infradead.org
>> Subject: Re: [PATCHv3 0/9] Support Xen versions up to xen-4.1
>>
> ...
>>
>> Thank you for your report, that's good.
>> So, I'll review these patches for makedumpfile-1.5.1.
>>
>>
>> Thanks
>> Atsushi Kumagai
> 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 897 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/kexec/attachments/20120917/4e612d99/attachment.sig>

From horms at verge.net.au  Mon Sep 17 21:15:43 2012
From: horms at verge.net.au (Simon Horman)
Date: Tue, 18 Sep 2012 10:15:43 +0900
Subject: [PATCH 0/7] kdump: Xen fixes
In-Reply-To: <ff6ec2d4-fe0b-4c2e-8547-567e887355d3@default>
References: <ff6ec2d4-fe0b-4c2e-8547-567e887355d3@default>
Message-ID: <20120918011543.GA28305@verge.net.au>

On Fri, Sep 14, 2012 at 06:01:53AM -0700, Daniel Kiper wrote:
> Hi Simon,
> 
> > do these relate to the changes that you were discussing
> > with Petr Tesarik in July?
> 
> No. They are independent of vmcoreinfo patch.

Thanks, all applied to the kexec-tools tree on kernel.org.


From kumagai-atsushi at mxc.nes.nec.co.jp  Tue Sep 18 02:38:03 2012
From: kumagai-atsushi at mxc.nes.nec.co.jp (Atsushi Kumagai)
Date: Tue, 18 Sep 2012 15:38:03 +0900
Subject: [PATCHv3 0/9] Support Xen versions up to xen-4.1
In-Reply-To: <0E9227E8EFCFF54EA493F6C0399C015D39C1018D5B@ABGEX70E.FSC.NET>
References: <201208241741.27573.petr@tesarici.cz>
 <0E9227E8EFCFF54EA493F6C0399C015D39BFC5A112@ABGEX70E.FSC.NET>
 <20120903140100.ac4dbf21401ace0e24a442d9@mxc.nes.nec.co.jp>
 <0E9227E8EFCFF54EA493F6C0399C015D39C0F0F687@ABGEX70E.FSC.NET>
 <505719BD.6080608@canonical.com>
 <0E9227E8EFCFF54EA493F6C0399C015D39C1018D5B@ABGEX70E.FSC.NET>
Message-ID: <20120918153803.dab06b1f45551ac81ddbbf83@mxc.nes.nec.co.jp>

Hello Norbert,

On Mon, 17 Sep 2012 18:52:57 +0200
"Trapp, Norbert" <norbert.trapp at ts.fujitsu.com> wrote:

> > Hi Norbert,
> > 
> > > When applying the makedumpfile Xen4 patches to the makedumpfile 1.5.0
> > > version and using it for a crash file to save just the dom0 and xen pages
> > > it again worked splendid in that makedumpfile was much faster than without
> > > the Xen4 patches. Alas I had to remove the OFFSET_IN_UNION_INIT(page._domain,
> > > "page_info", "domain") call because OFFSET_IN_UNION_INIT was no longer present.
> > > It didn't matter much because the call is only needed for makedumpfile -g or when
> > > using the /boot/xen-syms file. In the current 1.5.0  makedumpfile.c version you
> > > see
> > >
> > >     OFFSET_INIT(page_info._domain, "page_info", "u").
> > >
> > > The Xen4 patch modified this because the _domain structure member is in different
> > > unions for different version (x86, ia64) and may also not be the first entry in
> > > the union depending on the Xen version.
> > >
> > >     OFFSET_IN_UNION_INIT(page_info._domain, "page_info", "_domain");
> > >
> > > As an experiment I tried to use
> > >
> > 
> > >     OFFSET_INIT(page_info._domain, "page_info", "domain")

Sorry for my carelessness.
However, I still think that to integrate OFFSET_IN_UNION_INIT into OFFSET_INIT
is reasonable. So, please use OFFSET_INIT in v1.5.0 or later.

> > 
> > Just to make sure and since I am a bit lazy: with the Xen patch the page_info
> > structure has a member (somewhere) named domain? (or _domain)?
> > 
> 
> Just to get you on the right track, the struct page_info in the Xen code is meant.
> Not the one in the makedumpfile code.
> 
> For example in xen-4.1.3/xen/common/kexec.c:
> #ifdef __ia64__
>     VMCOREINFO_OFFSET_SUB(page_info, u.inuse, _domain);
> #else
>     VMCOREINFO_OFFSET_SUB(page_info, v.inuse, _domain);
> #endif
> 
> And the different page_info structures you find in:
> xen-4.1.3/xen/include/asm-ia64/mm.h
> xen-4.1.3/xen/include/asm-x86/mm.h
> 
> And also the structures can be different depending on the Xen version.
> 
> > >
> > > with makedumpfile 1.5.0. To get the correct offset I had to
> > > modify the dwarf_info.c code:
> > >
> > > --- ../makedumpfile-1.5.0/dwarf_info.c  2012-09-06 07:30:23.000000000 +0200
> > > +++ dwarf_info.c        2012-09-12 15:49:23.000000000 +0200
> > > @@ -449,8 +449,8 @@
> > >  static int
> > >  is_anonymous_container(Dwarf_Die *die)
> > >  {
> > > -       if (dwarf_diename(die))
> > > -               return FALSE;
> > > +       //if (dwarf_diename(die))
> > > +       //      return FALSE;
> > >         if (dwarf_tag(die) == DW_TAG_structure_type)
> > >                 return TRUE;
> > >         if (dwarf_info.cmd != DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION
> > > @@ -495,7 +495,7 @@
> > >                  * Descend into anonymous members and search for member
> > >                  * there.
> > >                  */
> > > -               if (!name) {
> > > +               if ((!name) || (strcmp(name, dwarf_info.member_name) != 0)) {
> > >                         if (!get_die_type(walker, &die_type))
> > >                                 continue;
> > >                         if (is_anonymous_container(&die_type))
> > >
> > >
> > > This is not a patch but just a description of what I modified for a test.
> > > The underlying question is why only the anonymous unions are used and not the
> > > ones with a name.
> > 
> > I made the patch because one element in some anonymous structure/union combo was
> > not found in newer kernels and the previous exceptions for such a thing were
> > hard coded. But as far as the dwarf info I was looking at the named
> > structures/unions were handled and I did not want to modify that case without a
> > way to test.

As for getting the offset, it is necessary to descend into structures/unions even
which are named.
So, I'll modify dwarf_info.c as below in the next version.


diff --git a/dwarf_info.c b/dwarf_info.c
index fb11e49..0c18dd1 100644
--- a/dwarf_info.c
+++ b/dwarf_info.c
@@ -447,10 +447,8 @@ get_dwarf_base_type(Dwarf_Die *die)
 }

 static int
-is_anonymous_container(Dwarf_Die *die)
+is_container(Dwarf_Die *die)
 {
-       if (dwarf_diename(die))
-               return FALSE;
        if (dwarf_tag(die) == DW_TAG_structure_type)
                return TRUE;
        if (dwarf_info.cmd != DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION
@@ -492,13 +490,13 @@ search_member(Dwarf_Die *die)
                        continue;

                /*
-                * Descend into anonymous members and search for member
+                * Descend into structures/unions and search for member
                 * there.
                 */
-               if (!name) {
+               if ((!name) || (strcmp(name, dwarf_info.member_name) != 0)) {
                        if (!get_die_type(walker, &die_type))
                                continue;
-                       if (is_anonymous_container(&die_type))
+                       if (is_container(&die_type))
                                if (search_member(&die_type)) {
                                        adjust_member_offset(walker);
                                        return TRUE;
@@ -1047,9 +1045,13 @@ get_member_offset(char *structname, char *membername, int cmd)
        dwarf_info.cmd = cmd;
        dwarf_info.struct_name = structname;
        dwarf_info.struct_size = NOT_FOUND_STRUCTURE;
-       dwarf_info.member_name = membername;
        dwarf_info.member_offset = NOT_FOUND_STRUCTURE;

+       if (dwarf_info.cmd == DWARF_INFO_GET_MEMBER_OFFSET_1ST_UNION)
+               dwarf_info.member_name = "";
+       else
+               dwarf_info.member_name = membername;
+
        if (!get_debug_info())
                return FAILED_DWARFINFO;

Thanks
Atsushi Kumagai


From indou.takao at jp.fujitsu.com  Tue Sep 18 21:52:43 2012
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Wed, 19 Sep 2012 10:52:43 +0900
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <20120914200334.GA9041@phenom.dumpdata.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com> <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com> <50473306.1070803@jp.fujitsu.com>
 <20120910143604.GB639@redhat.com> <504F1343.7030607@jp.fujitsu.com>
 <20120914200334.GA9041@phenom.dumpdata.com>
Message-ID: <5059256B.2010708@jp.fujitsu.com>

(2012/09/15 5:03), Konrad Rzeszutek Wilk wrote:
>> As to the boot parameter to enable this function, you suggested using
>> reset_devices. I found that on a certain platform resetting devices
>> caused PCIe error due to a hardware bug. Therefore I think we need
>> new parameter apart from reset_devices to disable this function on
>> such a machine.
>
> Wouldn't a DMI quirk be better for this? That way the second kernel
> internally would know not to do this.

That sounds good. I'll try it, thanks.

Thanks,
Takao Indoh



From kumagai-atsushi at mxc.nes.nec.co.jp  Thu Sep 20 03:25:35 2012
From: kumagai-atsushi at mxc.nes.nec.co.jp (Atsushi Kumagai)
Date: Thu, 20 Sep 2012 16:25:35 +0900
Subject: Query about cyclic buffer size
In-Reply-To: <20120913141018.GG4396@redhat.com>
References: <20120913141018.GG4396@redhat.com>
Message-ID: <20120920162535.63048af2d22e607a8f809133@mxc.nes.nec.co.jp>

Hello Vivek,

On Thu, 13 Sep 2012 10:10:18 -0400
Vivek Goyal <vgoyal at redhat.com> wrote:

> Hi Atsushi-san,
> 
> How is size of cyclic buffer decided with 1.5.0? In practice I don't think
> asking user for the size is a good idea as user does not know how much
> memory will be left after kernel boot.

As you said, I don't think asking user for the size is a smart way, either.
So, I agree with your basic idea explained in below.

> Will it make sense for makedumpfile to automatically determine the buffer
> size based on amount of free memory available in the system. Something
> like use 70-80% of free memory as cyclic buffer.

Now, I think makedumpfile should automatically choose the lesser of the two below
as the size of cyclic buffer when the size isn't specified:

  a. the size enough for storing the 1st/2nd bitmap for the whole of vmcore
  b. the limit size (e.g. 70-80% of free memory)

However, I don't have a good idea how to determine the appropriate size
for the case of "b". 
If someone have a idea for the limit size, please let me know.


By the way, I'll be on long vacation until Sep 30, so I can't reply.

Thanks
Atsushi kumagai


From ebiederm at xmission.com  Thu Sep 20 03:38:33 2012
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Thu, 20 Sep 2012 00:38:33 -0700
Subject: [RFC 1/3] PCI/PM: Fix kexec for D3cold and bridge suspending
In-Reply-To: <CAErSpo5fVbN2vD5Omc7dGJFWUccYZoCOVRF4YmXPe2Oxm81u5g@mail.gmail.com>
 (Bjorn Helgaas's message of "Mon, 17 Sep 2012 14:54:16 -0600")
References: <1347872076-5260-1-git-send-email-ying.huang@intel.com>
 <1347872076-5260-2-git-send-email-ying.huang@intel.com>
 <CAErSpo5fVbN2vD5Omc7dGJFWUccYZoCOVRF4YmXPe2Oxm81u5g@mail.gmail.com>
Message-ID: <877grpywhy.fsf@xmission.com>

Bjorn Helgaas <bhelgaas at google.com> writes:

> +cc Eric and kexec list
>
> On Mon, Sep 17, 2012 at 2:54 AM, Huang Ying <ying.huang at intel.com> wrote:
>> If PCI devices are put into D3cold before kexec, because the
>> configuration registers of PCI devices in D3cold are not accessible.
>>
>> And if PCI bridges are put into low power state before kexec,
>> configuration registers of PCI devices underneath the PCI bridges are
>> not accessible too.
>>
>> These will make some PCI devices can not be scanned after kexec, so
>> resume the PCI devices in D3cold or PCI bridges in low power state
>> before kexec.
>
> Don't we need to resume the device even without the kexec issue?  And
> even if it's in D1 or D2?

The basic requirement is that the device needs to be visible so we can
auto discover it.  As I recall most sleep states don't make the device
invisible and we can handle the rest in the device initializatoin code.

> It looks to me like pci_msi_shutdown() (and probably drv->shutdown())
> depend on the device being in D0.

There is certainly a depenency on the config registers being visible.
Although I don't know if much will go wrong if they aren't.

Ceratinly pci_msi_shutdown doesn't have anything to do if the device has
had so much power removed that the device is not even exectuing.

Eric

>> Signed-off-by: Huang Ying <ying.huang at intel.com>
>> ---
>>  drivers/pci/pci-driver.c |    4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> --- a/drivers/pci/pci-driver.c
>> +++ b/drivers/pci/pci-driver.c
>> @@ -421,6 +421,10 @@ static void pci_device_shutdown(struct d
>>         struct pci_dev *pci_dev = to_pci_dev(dev);
>>         struct pci_driver *drv = pci_dev->driver;
>>
>> +       /* Resume bridges and devices in D3cold for kexec to work properly */
>> +       if (pci_dev->current_state == PCI_D3cold || pci_dev->subordinate)
>> +               pm_runtime_resume(dev);
>> +
>>         if (drv && drv->shutdown)
>>                 drv->shutdown(pci_dev);
>>         pci_msi_shutdown(pci_dev);
>
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec


From ebiederm at xmission.com  Thu Sep 20 03:49:13 2012
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Thu, 20 Sep 2012 00:49:13 -0700
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <5053945F.9060107@hp.com> (Khalid Aziz's message of "Fri, 14 Sep
 2012 14:32:31 -0600")
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <5047DBA9.8030000@hp.com> <504815EB.9000701@redhat.com>
 <5048E40E.7040003@hp.com> <5049B6AD.9000304@redhat.com>
 <1347028634.20255.79.camel@lyra> <20120913133827.GB4396@redhat.com>
 <5053945F.9060107@hp.com>
Message-ID: <87mx0lxhfq.fsf@xmission.com>

Khalid Aziz <khalid.aziz at hp.com> writes:

> On 09/13/2012 07:38 AM, Vivek Goyal wrote:
>> So what does this mean? Second kernel assumes the regular BIOS and tries
>> to initialize that way? That sounds broken or is it just fine given
>> the fact we are anyway not planning to call into any of the efi services.
>> But what about memory maps, ACPI tables etc.
>
> Hi Vivek,
>
> My understanding on x86 side is not as clear as on ia64 side of kexec. From my
> reading of the code, second kernel seems to assume a regular BIOS. It searches
> through EBDA or upper memory region E0000h-FFFFFh to find RSDP, if an RSDP
> pointer was not passed to the second kernel. This works on my EFI machine which
> also implements a BIOS compatibility layer. I wonder how it works on pure EFI
> machines. Do pure EFI machines not implement, say EBDA? If yes,
> acpi_find_root_pointer() should fail tofind RSDP.As for memory map, all I can
> find are reference to e820 memory map which again assumes a BIOS but most EFI
> implementations I have come across implement a BIOS compatibility layer, so this
> will work still. I will look some more into this.

Kexec in general enters the kernel past the point where BIOS calls have
been made.  So basically the kexec path assumes no runtime services from
any firmware.  As I recall the e820 memory map can report the ACPI
location.

Last I checked we still had that useless set_virtual_memory map call in
the kernel when efi is detected and until that goes away I don't know
that we can or should depend on any efi bits in the kernel on the kdump
path.

Honestly I don't think we should make any EFI calls later than we make
BIOS calls, certainly the kdump case proves it works.

Eric


From ying.huang at intel.com  Thu Sep 20 04:19:33 2012
From: ying.huang at intel.com (Huang Ying)
Date: Thu, 20 Sep 2012 16:19:33 +0800
Subject: [RFC 1/3] PCI/PM: Fix kexec for D3cold and bridge suspending
In-Reply-To: <877grpywhy.fsf@xmission.com>
References: <1347872076-5260-1-git-send-email-ying.huang@intel.com>
 <1347872076-5260-2-git-send-email-ying.huang@intel.com>
 <CAErSpo5fVbN2vD5Omc7dGJFWUccYZoCOVRF4YmXPe2Oxm81u5g@mail.gmail.com>
 <877grpywhy.fsf@xmission.com>
Message-ID: <1348129173.8212.218.camel@yhuang-dev>

On Thu, 2012-09-20 at 00:38 -0700, Eric W. Biederman wrote:
> Bjorn Helgaas <bhelgaas at google.com> writes:
> 
> > +cc Eric and kexec list
> >
> > On Mon, Sep 17, 2012 at 2:54 AM, Huang Ying <ying.huang at intel.com> wrote:
> >> If PCI devices are put into D3cold before kexec, because the
> >> configuration registers of PCI devices in D3cold are not accessible.
> >>
> >> And if PCI bridges are put into low power state before kexec,
> >> configuration registers of PCI devices underneath the PCI bridges are
> >> not accessible too.
> >>
> >> These will make some PCI devices can not be scanned after kexec, so
> >> resume the PCI devices in D3cold or PCI bridges in low power state
> >> before kexec.
> >
> > Don't we need to resume the device even without the kexec issue?  And
> > even if it's in D1 or D2?
> 
> The basic requirement is that the device needs to be visible so we can
> auto discover it.  As I recall most sleep states don't make the device
> invisible and we can handle the rest in the device initializatoin code.

PCI devices in D3cold or under a bridge in D3hot will not be visible, so
we must fix that for kexec to run properly.

> > It looks to me like pci_msi_shutdown() (and probably drv->shutdown())
> > depend on the device being in D0.
> 
> There is certainly a depenency on the config registers being visible.
> Although I don't know if much will go wrong if they aren't.
> 
> Ceratinly pci_msi_shutdown doesn't have anything to do if the device has
> had so much power removed that the device is not even exectuing.

Don't know which power state device should be in for pci_msi_shutdown
etc.  But it appears that normal shutdown/reboot and kexec works at most
times so far.  D3cold and bridge in D3hot works for normal
shutdown/reboot, but not for kexec.  So I write some fix.

Best Regards,
Huang Ying

> >> Signed-off-by: Huang Ying <ying.huang at intel.com>
> >> ---
> >>  drivers/pci/pci-driver.c |    4 ++++
> >>  1 file changed, 4 insertions(+)
> >>
> >> --- a/drivers/pci/pci-driver.c
> >> +++ b/drivers/pci/pci-driver.c
> >> @@ -421,6 +421,10 @@ static void pci_device_shutdown(struct d
> >>         struct pci_dev *pci_dev = to_pci_dev(dev);
> >>         struct pci_driver *drv = pci_dev->driver;
> >>
> >> +       /* Resume bridges and devices in D3cold for kexec to work properly */
> >> +       if (pci_dev->current_state == PCI_D3cold || pci_dev->subordinate)
> >> +               pm_runtime_resume(dev);
> >> +
> >>         if (drv && drv->shutdown)
> >>                 drv->shutdown(pci_dev);
> >>         pci_msi_shutdown(pci_dev);
> >
> > _______________________________________________
> > kexec mailing list
> > kexec at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/kexec




From ebiederm at xmission.com  Thu Sep 20 04:27:33 2012
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Thu, 20 Sep 2012 01:27:33 -0700
Subject: [RFC 1/3] PCI/PM: Fix kexec for D3cold and bridge suspending
In-Reply-To: <1348129173.8212.218.camel@yhuang-dev> (Huang Ying's message of
 "Thu, 20 Sep 2012 16:19:33 +0800")
References: <1347872076-5260-1-git-send-email-ying.huang@intel.com>
 <1347872076-5260-2-git-send-email-ying.huang@intel.com>
 <CAErSpo5fVbN2vD5Omc7dGJFWUccYZoCOVRF4YmXPe2Oxm81u5g@mail.gmail.com>
 <877grpywhy.fsf@xmission.com> <1348129173.8212.218.camel@yhuang-dev>
Message-ID: <87fw6dxfnu.fsf@xmission.com>

Huang Ying <ying.huang at intel.com> writes:

> On Thu, 2012-09-20 at 00:38 -0700, Eric W. Biederman wrote:
>> Bjorn Helgaas <bhelgaas at google.com> writes:
>> 
>> > +cc Eric and kexec list
>> >
>> > On Mon, Sep 17, 2012 at 2:54 AM, Huang Ying <ying.huang at intel.com> wrote:
>> >> If PCI devices are put into D3cold before kexec, because the
>> >> configuration registers of PCI devices in D3cold are not accessible.
>> >>
>> >> And if PCI bridges are put into low power state before kexec,
>> >> configuration registers of PCI devices underneath the PCI bridges are
>> >> not accessible too.
>> >>
>> >> These will make some PCI devices can not be scanned after kexec, so
>> >> resume the PCI devices in D3cold or PCI bridges in low power state
>> >> before kexec.
>> >
>> > Don't we need to resume the device even without the kexec issue?  And
>> > even if it's in D1 or D2?
>> 
>> The basic requirement is that the device needs to be visible so we can
>> auto discover it.  As I recall most sleep states don't make the device
>> invisible and we can handle the rest in the device initializatoin code.
>
> PCI devices in D3cold or under a bridge in D3hot will not be visible, so
> we must fix that for kexec to run properly.

That seems reasonable to me.

>> > It looks to me like pci_msi_shutdown() (and probably drv->shutdown())
>> > depend on the device being in D0.
>> 
>> There is certainly a depenency on the config registers being visible.
>> Although I don't know if much will go wrong if they aren't.
>> 
>> Ceratinly pci_msi_shutdown doesn't have anything to do if the device has
>> had so much power removed that the device is not even exectuing.
>
> Don't know which power state device should be in for pci_msi_shutdown
> etc.  But it appears that normal shutdown/reboot and kexec works at most
> times so far.  D3cold and bridge in D3hot works for normal
> shutdown/reboot, but not for kexec.  So I write some fix.

To be clear.  Has someone picked up this patch yet?

Acked-by: "Eric W. Biederman" <ebiederm at xmission.com>

As for reboot it tends to always work because frequently the firmware
code triggers a soft reset of the entire machine, which puts devices in
their power on reset state, which is not a suspended state.  Although
that behavior is not required for a software reboot.

Eric



> Best Regards,
> Huang Ying
>
>> >> Signed-off-by: Huang Ying <ying.huang at intel.com>
>> >> ---
>> >>  drivers/pci/pci-driver.c |    4 ++++
>> >>  1 file changed, 4 insertions(+)
>> >>
>> >> --- a/drivers/pci/pci-driver.c
>> >> +++ b/drivers/pci/pci-driver.c
>> >> @@ -421,6 +421,10 @@ static void pci_device_shutdown(struct d
>> >>         struct pci_dev *pci_dev = to_pci_dev(dev);
>> >>         struct pci_driver *drv = pci_dev->driver;
>> >>
>> >> +       /* Resume bridges and devices in D3cold for kexec to work properly */
>> >> +       if (pci_dev->current_state == PCI_D3cold || pci_dev->subordinate)
>> >> +               pm_runtime_resume(dev);
>> >> +
>> >>         if (drv && drv->shutdown)
>> >>                 drv->shutdown(pci_dev);
>> >>         pci_msi_shutdown(pci_dev);
>> >
>> > _______________________________________________
>> > kexec mailing list
>> > kexec at lists.infradead.org
>> > http://lists.infradead.org/mailman/listinfo/kexec


From vgoyal at redhat.com  Thu Sep 20 09:12:41 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Thu, 20 Sep 2012 09:12:41 -0400
Subject: Query about cyclic buffer size
In-Reply-To: <20120920162535.63048af2d22e607a8f809133@mxc.nes.nec.co.jp>
References: <20120913141018.GG4396@redhat.com>
 <20120920162535.63048af2d22e607a8f809133@mxc.nes.nec.co.jp>
Message-ID: <20120920131241.GA4681@redhat.com>

On Thu, Sep 20, 2012 at 04:25:35PM +0900, Atsushi Kumagai wrote:
> Hello Vivek,
> 
> On Thu, 13 Sep 2012 10:10:18 -0400
> Vivek Goyal <vgoyal at redhat.com> wrote:
> 
> > Hi Atsushi-san,
> > 
> > How is size of cyclic buffer decided with 1.5.0? In practice I don't think
> > asking user for the size is a good idea as user does not know how much
> > memory will be left after kernel boot.
> 
> As you said, I don't think asking user for the size is a smart way, either.
> So, I agree with your basic idea explained in below.
> 
> > Will it make sense for makedumpfile to automatically determine the buffer
> > size based on amount of free memory available in the system. Something
> > like use 70-80% of free memory as cyclic buffer.
> 
> Now, I think makedumpfile should automatically choose the lesser of the two below
> as the size of cyclic buffer when the size isn't specified:
> 
>   a. the size enough for storing the 1st/2nd bitmap for the whole of vmcore
>   b. the limit size (e.g. 70-80% of free memory)
> 
> However, I don't have a good idea how to determine the appropriate size
> for the case of "b". 
> If someone have a idea for the limit size, please let me know.

May be just look at "free" output or "cat /proc/meminfo" and grep for
"MemFree" calculate the size of buffer.

Thanks
Vivek


From rjw at sisk.pl  Thu Sep 20 15:20:31 2012
From: rjw at sisk.pl (Rafael J. Wysocki)
Date: Thu, 20 Sep 2012 21:20:31 +0200
Subject: [RFC 1/3] PCI/PM: Fix kexec for D3cold and bridge suspending
In-Reply-To: <CAErSpo5fVbN2vD5Omc7dGJFWUccYZoCOVRF4YmXPe2Oxm81u5g@mail.gmail.com>
References: <1347872076-5260-1-git-send-email-ying.huang@intel.com>
 <1347872076-5260-2-git-send-email-ying.huang@intel.com>
 <CAErSpo5fVbN2vD5Omc7dGJFWUccYZoCOVRF4YmXPe2Oxm81u5g@mail.gmail.com>
Message-ID: <201209202120.32029.rjw@sisk.pl>

On Monday, September 17, 2012, Bjorn Helgaas wrote:
> +cc Eric and kexec list
> 
> On Mon, Sep 17, 2012 at 2:54 AM, Huang Ying <ying.huang at intel.com> wrote:
> > If PCI devices are put into D3cold before kexec, because the
> > configuration registers of PCI devices in D3cold are not accessible.
> >
> > And if PCI bridges are put into low power state before kexec,
> > configuration registers of PCI devices underneath the PCI bridges are
> > not accessible too.
> >
> > These will make some PCI devices can not be scanned after kexec, so
> > resume the PCI devices in D3cold or PCI bridges in low power state
> > before kexec.
> 
> Don't we need to resume the device even without the kexec issue?  And
> even if it's in D1 or D2?
> 
> It looks to me like pci_msi_shutdown() (and probably drv->shutdown())
> depend on the device being in D0.

We should in theory, but we didn't do any power management of PCI bridges
before, so this is the first time we have a problem with it.

So I'd say, yeah, let's resume if current_state is between D1 and D3cold
inclusive and the kexec comment is not very helpful (the problem is not
kexec-specific in general).

Speaking of kexec, it might consider using the hibernation device freeze
instead of device shutdown (which the kexec jump feature does).  I've seen
reports of problems that would be solved this way most likely.

Thanks,
Rafael


> > Signed-off-by: Huang Ying <ying.huang at intel.com>
> > ---
> >  drivers/pci/pci-driver.c |    4 ++++
> >  1 file changed, 4 insertions(+)
> >
> > --- a/drivers/pci/pci-driver.c
> > +++ b/drivers/pci/pci-driver.c
> > @@ -421,6 +421,10 @@ static void pci_device_shutdown(struct d
> >         struct pci_dev *pci_dev = to_pci_dev(dev);
> >         struct pci_driver *drv = pci_dev->driver;
> >
> > +       /* Resume bridges and devices in D3cold for kexec to work properly */
> > +       if (pci_dev->current_state == PCI_D3cold || pci_dev->subordinate)
> > +               pm_runtime_resume(dev);
> > +
> >         if (drv && drv->shutdown)
> >                 drv->shutdown(pci_dev);
> >         pci_msi_shutdown(pci_dev);
> 
> 



From vgoyal at redhat.com  Thu Sep 20 16:06:34 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Thu, 20 Sep 2012 16:06:34 -0400
Subject: makedumpfile 1.5.0 takes much more time to dump
Message-ID: <20120920200633.GL4681@redhat.com>

Hi Atsushi san,

We tried makedumpfile 1.5.0 on a 1TB machine and it seems to regress
badly. We reserved 192MB of memory and following are test results.

#1. makedumpfile-1.4.2 -E --message-level 1 -d 31
real     3m47.520s
user     0m56.543s
sys	 2m41.631s

#2. makedumpfile-1.5.0 -E --message-level 1 -d 31
real     52m25.262s
user     32m51.310s
sys	 18m53.265s

#3. makedumpfile-1.4.2 -c --message-level 1 -d 31
real     8m49.107s
user     4m34.180s
sys	 4m8.691s

#4. makedumpfile-1.5.0 -c --message-level 1 -d 31
real     46m48.985s
user     29m35.203s
sys	 16m43.149s

Thanks
Vivek







From d.hatayama at jp.fujitsu.com  Thu Sep 20 20:23:57 2012
From: d.hatayama at jp.fujitsu.com (HATAYAMA Daisuke)
Date: Fri, 21 Sep 2012 09:23:57 +0900 (JST)
Subject: makedumpfile 1.5.0 takes much more time to dump
In-Reply-To: <20120920200633.GL4681@redhat.com>
References: <20120920200633.GL4681@redhat.com>
Message-ID: <20120921.092357.94103398.d.hatayama@jp.fujitsu.com>

From: Vivek Goyal <vgoyal at redhat.com>
Subject: makedumpfile 1.5.0 takes much more time to dump
Date: Thu, 20 Sep 2012 16:06:34 -0400

> Hi Atsushi san,
> 
> We tried makedumpfile 1.5.0 on a 1TB machine and it seems to regress
> badly. We reserved 192MB of memory and following are test results.
> 
> #1. makedumpfile-1.4.2 -E --message-level 1 -d 31
> real     3m47.520s
> user     0m56.543s
> sys	 2m41.631s
> 
> #2. makedumpfile-1.5.0 -E --message-level 1 -d 31
> real     52m25.262s
> user     32m51.310s
> sys	 18m53.265s
> 
> #3. makedumpfile-1.4.2 -c --message-level 1 -d 31
> real     8m49.107s
> user     4m34.180s
> sys	 4m8.691s
> 
> #4. makedumpfile-1.5.0 -c --message-level 1 -d 31
> real     46m48.985s
> user     29m35.203s
> sys	 16m43.149s
> 

Hello Vivek,

On v1.5.0 we cannot filter free pages in constant space becuase we
have yet to test it. Instead, the existing method is used here, which
repeats walking on a whole page frames the number of cycles times.

As Kumagai-san explains, the number of cycles can be calculated by the
following expression:

  N = physical memory size / (page size * bit per byte(8) * BUFSIZE_CYCLIC)

So,

  N = 2TB / (4KB * 8 * 1MB) = 64 cycles.

I guess on this environment, it took about 50 seconds to filter free
pages in one cycle.

Thanks.
HATAYAMA, Daisuke



From ying.huang at intel.com  Thu Sep 20 20:28:42 2012
From: ying.huang at intel.com (Huang Ying)
Date: Fri, 21 Sep 2012 08:28:42 +0800
Subject: [RFC 1/3] PCI/PM: Fix kexec for D3cold and bridge suspending
In-Reply-To: <201209202120.32029.rjw@sisk.pl>
References: <1347872076-5260-1-git-send-email-ying.huang@intel.com>
 <1347872076-5260-2-git-send-email-ying.huang@intel.com>
 <CAErSpo5fVbN2vD5Omc7dGJFWUccYZoCOVRF4YmXPe2Oxm81u5g@mail.gmail.com>
 <201209202120.32029.rjw@sisk.pl>
Message-ID: <1348187322.8212.224.camel@yhuang-dev>

On Thu, 2012-09-20 at 21:20 +0200, Rafael J. Wysocki wrote:
> On Monday, September 17, 2012, Bjorn Helgaas wrote:
> > +cc Eric and kexec list
> > 
> > On Mon, Sep 17, 2012 at 2:54 AM, Huang Ying <ying.huang at intel.com> wrote:
> > > If PCI devices are put into D3cold before kexec, because the
> > > configuration registers of PCI devices in D3cold are not accessible.
> > >
> > > And if PCI bridges are put into low power state before kexec,
> > > configuration registers of PCI devices underneath the PCI bridges are
> > > not accessible too.
> > >
> > > These will make some PCI devices can not be scanned after kexec, so
> > > resume the PCI devices in D3cold or PCI bridges in low power state
> > > before kexec.
> > 
> > Don't we need to resume the device even without the kexec issue?  And
> > even if it's in D1 or D2?
> > 
> > It looks to me like pci_msi_shutdown() (and probably drv->shutdown())
> > depend on the device being in D0.
> 
> We should in theory, but we didn't do any power management of PCI bridges
> before, so this is the first time we have a problem with it.
> 
> So I'd say, yeah, let's resume if current_state is between D1 and D3cold
> inclusive and the kexec comment is not very helpful (the problem is not
> kexec-specific in general).

Resume from D1 to D3cold for any device or just bridges?

Best Regards,
Huang Ying

> Speaking of kexec, it might consider using the hibernation device freeze
> instead of device shutdown (which the kexec jump feature does).  I've seen
> reports of problems that would be solved this way most likely.
> 
> Thanks,
> Rafael
> 
> 
> > > Signed-off-by: Huang Ying <ying.huang at intel.com>
> > > ---
> > >  drivers/pci/pci-driver.c |    4 ++++
> > >  1 file changed, 4 insertions(+)
> > >
> > > --- a/drivers/pci/pci-driver.c
> > > +++ b/drivers/pci/pci-driver.c
> > > @@ -421,6 +421,10 @@ static void pci_device_shutdown(struct d
> > >         struct pci_dev *pci_dev = to_pci_dev(dev);
> > >         struct pci_driver *drv = pci_dev->driver;
> > >
> > > +       /* Resume bridges and devices in D3cold for kexec to work properly */
> > > +       if (pci_dev->current_state == PCI_D3cold || pci_dev->subordinate)
> > > +               pm_runtime_resume(dev);
> > > +
> > >         if (drv && drv->shutdown)
> > >                 drv->shutdown(pci_dev);
> > >         pci_msi_shutdown(pci_dev);
> > 
> > 
> 




From d.hatayama at jp.fujitsu.com  Thu Sep 20 20:43:42 2012
From: d.hatayama at jp.fujitsu.com (HATAYAMA Daisuke)
Date: Fri, 21 Sep 2012 09:43:42 +0900 (JST)
Subject: makedumpfile 1.5.0 takes much more time to dump
In-Reply-To: <20120921.092357.94103398.d.hatayama@jp.fujitsu.com>
References: <20120920200633.GL4681@redhat.com>
 <20120921.092357.94103398.d.hatayama@jp.fujitsu.com>
Message-ID: <20120921.094342.284366330.d.hatayama@jp.fujitsu.com>

From: HATAYAMA Daisuke <d.hatayama at jp.fujitsu.com>
Subject: Re: makedumpfile 1.5.0 takes much more time to dump
Date: Fri, 21 Sep 2012 09:23:57 +0900

> From: Vivek Goyal <vgoyal at redhat.com>
> Subject: makedumpfile 1.5.0 takes much more time to dump
> Date: Thu, 20 Sep 2012 16:06:34 -0400
> 
>> Hi Atsushi san,
>> 
>> We tried makedumpfile 1.5.0 on a 1TB machine and it seems to regress
>> badly. We reserved 192MB of memory and following are test results.
>> 
>> #1. makedumpfile-1.4.2 -E --message-level 1 -d 31
>> real     3m47.520s
>> user     0m56.543s
>> sys	 2m41.631s
>> 
>> #2. makedumpfile-1.5.0 -E --message-level 1 -d 31
>> real     52m25.262s
>> user     32m51.310s
>> sys	 18m53.265s
>> 
>> #3. makedumpfile-1.4.2 -c --message-level 1 -d 31
>> real     8m49.107s
>> user     4m34.180s
>> sys	 4m8.691s
>> 
>> #4. makedumpfile-1.5.0 -c --message-level 1 -d 31
>> real     46m48.985s
>> user     29m35.203s
>> sys	 16m43.149s
>> 
> 
> Hello Vivek,
> 
> On v1.5.0 we cannot filter free pages in constant space becuase we
> have yet to test it. Instead, the existing method is used here, which
> repeats walking on a whole page frames the number of cycles times.
> 
> As Kumagai-san explains, the number of cycles can be calculated by the
> following expression:
> 
>   N = physical memory size / (page size * bit per byte(8) * BUFSIZE_CYCLIC)
> 
> So,
> 
>   N = 2TB / (4KB * 8 * 1MB) = 64 cycles.
> 
> I guess on this environment, it took about 50 seconds to filter free
> pages in one cycle.
> 

I noticed a careless miss. 1TB is correct on your case.

   N = 1TB / (4KB * 8 * 1MB) = 32 cycles.

So, about 95 seconds for one cycle?

Thanks.
HATAYAMA, Daisuke



From vgoyal at redhat.com  Fri Sep 21 09:32:32 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Fri, 21 Sep 2012 09:32:32 -0400
Subject: makedumpfile 1.5.0 takes much more time to dump
In-Reply-To: <20120921.092357.94103398.d.hatayama@jp.fujitsu.com>
References: <20120920200633.GL4681@redhat.com>
 <20120921.092357.94103398.d.hatayama@jp.fujitsu.com>
Message-ID: <20120921133232.GC15909@redhat.com>

On Fri, Sep 21, 2012 at 09:23:57AM +0900, HATAYAMA Daisuke wrote:
> From: Vivek Goyal <vgoyal at redhat.com>
> Subject: makedumpfile 1.5.0 takes much more time to dump
> Date: Thu, 20 Sep 2012 16:06:34 -0400
> 
> > Hi Atsushi san,
> > 
> > We tried makedumpfile 1.5.0 on a 1TB machine and it seems to regress
> > badly. We reserved 192MB of memory and following are test results.
> > 
> > #1. makedumpfile-1.4.2 -E --message-level 1 -d 31
> > real     3m47.520s
> > user     0m56.543s
> > sys	 2m41.631s
> > 
> > #2. makedumpfile-1.5.0 -E --message-level 1 -d 31
> > real     52m25.262s
> > user     32m51.310s
> > sys	 18m53.265s
> > 
> > #3. makedumpfile-1.4.2 -c --message-level 1 -d 31
> > real     8m49.107s
> > user     4m34.180s
> > sys	 4m8.691s
> > 
> > #4. makedumpfile-1.5.0 -c --message-level 1 -d 31
> > real     46m48.985s
> > user     29m35.203s
> > sys	 16m43.149s
> > 
> 
> Hello Vivek,
> 
> On v1.5.0 we cannot filter free pages in constant space becuase we
> have yet to test it. Instead, the existing method is used here, which
> repeats walking on a whole page frames the number of cycles times.
> 
> As Kumagai-san explains, the number of cycles can be calculated by the
> following expression:
> 
>   N = physical memory size / (page size * bit per byte(8) * BUFSIZE_CYCLIC)
> 
> So,
> 
>   N = 2TB / (4KB * 8 * 1MB) = 64 cycles.
> 
> I guess on this environment, it took about 50 seconds to filter free
> pages in one cycle.

Ok, so once we have your walking through page struct patches in, hopefully
this problem will be gone?

If that's going to take time, can we make using of new logic conditional
on a command line option. So that user has the option of using old
logic.

Thanks
Vivek


From ddutile at redhat.com  Fri Sep 21 13:57:53 2012
From: ddutile at redhat.com (Don Dutile)
Date: Fri, 21 Sep 2012 13:57:53 -0400
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <20120914200334.GA9041@phenom.dumpdata.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com> <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com> <50473306.1070803@jp.fujitsu.com>
 <20120910143604.GB639@redhat.com> <504F1343.7030607@jp.fujitsu.com>
 <20120914200334.GA9041@phenom.dumpdata.com>
Message-ID: <505CAAA1.3040409@redhat.com>

On 09/14/2012 04:03 PM, Konrad Rzeszutek Wilk wrote:
>> As to the boot parameter to enable this function, you suggested using
>> reset_devices. I found that on a certain platform resetting devices
>> caused PCIe error due to a hardware bug. Therefore I think we need
>> new parameter apart from reset_devices to disable this function on
>> such a machine.
>
> Wouldn't a DMI quirk be better for this? That way the second kernel
> internally would know not to do this.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
a DMI quirk for a PCIe switch?  pci-quirk maybe?  there is a hook
in per-device pci reset code path, which could be setup for such
a case.



From rjw at sisk.pl  Fri Sep 21 15:30:49 2012
From: rjw at sisk.pl (Rafael J. Wysocki)
Date: Fri, 21 Sep 2012 21:30:49 +0200
Subject: [RFC 1/3] PCI/PM: Fix kexec for D3cold and bridge suspending
In-Reply-To: <1348187322.8212.224.camel@yhuang-dev>
References: <1347872076-5260-1-git-send-email-ying.huang@intel.com>
 <201209202120.32029.rjw@sisk.pl> <1348187322.8212.224.camel@yhuang-dev>
Message-ID: <201209212130.50085.rjw@sisk.pl>

On Friday, September 21, 2012, Huang Ying wrote:
> On Thu, 2012-09-20 at 21:20 +0200, Rafael J. Wysocki wrote:
> > On Monday, September 17, 2012, Bjorn Helgaas wrote:
> > > +cc Eric and kexec list
> > > 
> > > On Mon, Sep 17, 2012 at 2:54 AM, Huang Ying <ying.huang at intel.com> wrote:
> > > > If PCI devices are put into D3cold before kexec, because the
> > > > configuration registers of PCI devices in D3cold are not accessible.
> > > >
> > > > And if PCI bridges are put into low power state before kexec,
> > > > configuration registers of PCI devices underneath the PCI bridges are
> > > > not accessible too.
> > > >
> > > > These will make some PCI devices can not be scanned after kexec, so
> > > > resume the PCI devices in D3cold or PCI bridges in low power state
> > > > before kexec.
> > > 
> > > Don't we need to resume the device even without the kexec issue?  And
> > > even if it's in D1 or D2?
> > > 
> > > It looks to me like pci_msi_shutdown() (and probably drv->shutdown())
> > > depend on the device being in D0.
> > 
> > We should in theory, but we didn't do any power management of PCI bridges
> > before, so this is the first time we have a problem with it.
> > 
> > So I'd say, yeah, let's resume if current_state is between D1 and D3cold
> > inclusive and the kexec comment is not very helpful (the problem is not
> > kexec-specific in general).
> 
> Resume from D1 to D3cold for any device or just bridges?

I'd say every device for starters.

Thanks,
Rafael


> > Speaking of kexec, it might consider using the hibernation device freeze
> > instead of device shutdown (which the kexec jump feature does).  I've seen
> > reports of problems that would be solved this way most likely.
> > 
> > Thanks,
> > Rafael
> > 
> > 
> > > > Signed-off-by: Huang Ying <ying.huang at intel.com>
> > > > ---
> > > >  drivers/pci/pci-driver.c |    4 ++++
> > > >  1 file changed, 4 insertions(+)
> > > >
> > > > --- a/drivers/pci/pci-driver.c
> > > > +++ b/drivers/pci/pci-driver.c
> > > > @@ -421,6 +421,10 @@ static void pci_device_shutdown(struct d
> > > >         struct pci_dev *pci_dev = to_pci_dev(dev);
> > > >         struct pci_driver *drv = pci_dev->driver;
> > > >
> > > > +       /* Resume bridges and devices in D3cold for kexec to work properly */
> > > > +       if (pci_dev->current_state == PCI_D3cold || pci_dev->subordinate)
> > > > +               pm_runtime_resume(dev);
> > > > +
> > > >         if (drv && drv->shutdown)
> > > >                 drv->shutdown(pci_dev);
> > > >         pci_msi_shutdown(pci_dev);
> > > 
> > > 
> > 
> 
> 
> 
> 



From khalid.aziz at hp.com  Fri Sep 21 18:50:39 2012
From: khalid.aziz at hp.com (Khalid Aziz)
Date: Fri, 21 Sep 2012 16:50:39 -0600
Subject: [PATCH]kdump: pass noefi and acpi_rsdp= to 2nd kernel
In-Reply-To: <87mx0lxhfq.fsf@xmission.com>
References: <20120905054445.GA6370@dhcp-16-143.nay.redhat.com>
 <5047DBA9.8030000@hp.com> <504815EB.9000701@redhat.com>
 <5048E40E.7040003@hp.com> <5049B6AD.9000304@redhat.com>
 <1347028634.20255.79.camel@lyra> <20120913133827.GB4396@redhat.com>
 <5053945F.9060107@hp.com> <87mx0lxhfq.fsf@xmission.com>
Message-ID: <1348267839.23545.2.camel@concerto.americas.hpqcorp.net>

On Thu, 2012-09-20 at 00:49 -0700, Eric W. Biederman wrote:
> Last I checked we still had that useless set_virtual_memory map call in
> the kernel when efi is detected and until that goes away I don't know
> that we can or should depend on any efi bits in the kernel on the kdump
> path.
> 
> Honestly I don't think we should make any EFI calls later than we make
> BIOS calls, certainly the kdump case proves it works.
> 
> Eric

I would agree for the most part about not making any EFI calls from the
kernel but there are couple of cases where we may have to rethink that.
One is accessing the hardware clock. On a pure EFI and legacy-free
machine, we will need to access hardware through EFI runtime services.
The other one being access to EFI variables. We can choose to not use
EFI variables but we might be giving up some useful functionality.

-- 
Khalid Aziz <khalid.aziz at hp.com>



From d.hatayama at jp.fujitsu.com  Sun Sep 23 20:51:12 2012
From: d.hatayama at jp.fujitsu.com (HATAYAMA Daisuke)
Date: Mon, 24 Sep 2012 09:51:12 +0900 (JST)
Subject: makedumpfile 1.5.0 takes much more time to dump
In-Reply-To: <20120921133232.GC15909@redhat.com>
References: <20120920200633.GL4681@redhat.com>
 <20120921.092357.94103398.d.hatayama@jp.fujitsu.com>
 <20120921133232.GC15909@redhat.com>
Message-ID: <20120924.095112.153507503.d.hatayama@jp.fujitsu.com>

From: Vivek Goyal <vgoyal at redhat.com>
Subject: Re: makedumpfile 1.5.0 takes much more time to dump
Date: Fri, 21 Sep 2012 09:32:32 -0400

> On Fri, Sep 21, 2012 at 09:23:57AM +0900, HATAYAMA Daisuke wrote:
>> From: Vivek Goyal <vgoyal at redhat.com>
>> Subject: makedumpfile 1.5.0 takes much more time to dump
>> Date: Thu, 20 Sep 2012 16:06:34 -0400
>> 
>> > Hi Atsushi san,
>> > 
>> > We tried makedumpfile 1.5.0 on a 1TB machine and it seems to regress
>> > badly. We reserved 192MB of memory and following are test results.
>> > 
>> > #1. makedumpfile-1.4.2 -E --message-level 1 -d 31
>> > real     3m47.520s
>> > user     0m56.543s
>> > sys	 2m41.631s
>> > 
>> > #2. makedumpfile-1.5.0 -E --message-level 1 -d 31
>> > real     52m25.262s
>> > user     32m51.310s
>> > sys	 18m53.265s
>> > 
>> > #3. makedumpfile-1.4.2 -c --message-level 1 -d 31
>> > real     8m49.107s
>> > user     4m34.180s
>> > sys	 4m8.691s
>> > 
>> > #4. makedumpfile-1.5.0 -c --message-level 1 -d 31
>> > real     46m48.985s
>> > user     29m35.203s
>> > sys	 16m43.149s
>> > 
>> 
>> Hello Vivek,
>> 
>> On v1.5.0 we cannot filter free pages in constant space becuase we
>> have yet to test it. Instead, the existing method is used here, which
>> repeats walking on a whole page frames the number of cycles times.
>> 
>> As Kumagai-san explains, the number of cycles can be calculated by the
>> following expression:
>> 
>>   N = physical memory size / (page size * bit per byte(8) * BUFSIZE_CYCLIC)
>> 
>> So,
>> 
>>   N = 2TB / (4KB * 8 * 1MB) = 64 cycles.
>> 
>> I guess on this environment, it took about 50 seconds to filter free
>> pages in one cycle.
> 
> Ok, so once we have your walking through page struct patches in, hopefully
> this problem will be gone?
> 

Yes, then free page filtering is integrated in other mem_map array
logics. You can see how it takes from the following message.

Excluding unnecessary pages        : [100 %] STEP [Excluding unnecessary pages] : 0.204574 seconds

New logic takes equal to or quicker than the total time indicated by
the above kind of messages now.

> If that's going to take time, can we make using of new logic conditional
> on a command line option. So that user has the option of using old
> logic.
> 

Kumagai-san should decide this. 

BTW, Kumagai-san, in what version do you plan release of this new
mem_map logic? Around v1.5.2? I want to re-send a new patch set to
which I add small changes and comments for maintainability.

Thanks.
HATAYAMA, Daisuke



From indou.takao at jp.fujitsu.com  Mon Sep 24 07:12:02 2012
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Mon, 24 Sep 2012 20:12:02 +0900
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <505CAAA1.3040409@redhat.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com> <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com> <50473306.1070803@jp.fujitsu.com>
 <20120910143604.GB639@redhat.com> <504F1343.7030607@jp.fujitsu.com>
 <20120914200334.GA9041@phenom.dumpdata.com> <505CAAA1.3040409@redhat.com>
Message-ID: <50604002.8050500@jp.fujitsu.com>

(2012/09/22 2:57), Don Dutile wrote:
> On 09/14/2012 04:03 PM, Konrad Rzeszutek Wilk wrote:
>>> As to the boot parameter to enable this function, you suggested using
>>> reset_devices. I found that on a certain platform resetting devices
>>> caused PCIe error due to a hardware bug. Therefore I think we need
>>> new parameter apart from reset_devices to disable this function on
>>> such a machine.
>>
>> Wouldn't a DMI quirk be better for this? That way the second kernel
>> internally would know not to do this.
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> a DMI quirk for a PCIe switch?  pci-quirk maybe?  there is a hook
> in per-device pci reset code path, which could be setup for such
> a case.

Yep, I think early-quirk is better.

Thanks,
Takao Indoh



From indou.takao at jp.fujitsu.com  Mon Sep 24 07:22:02 2012
From: indou.takao at jp.fujitsu.com (Takao Indoh)
Date: Mon, 24 Sep 2012 20:22:02 +0900
Subject: [RFC][PATCH] Reset PCIe devices to address DMA problem on kdump
 with iommu
In-Reply-To: <20120914154817.GE6221@redhat.com>
References: <501BB4EF.7080909@jp.fujitsu.com>
 <20120803114643.GA28330@redhat.com> <501F4877.5050605@jp.fujitsu.com>
 <20120806203902.GH25559@redhat.com> <50473306.1070803@jp.fujitsu.com>
 <20120910143604.GB639@redhat.com> <504F1343.7030607@jp.fujitsu.com>
 <20120911144323.GF12039@redhat.com> <50504F47.80909@jp.fujitsu.com>
 <20120914154817.GE6221@redhat.com>
Message-ID: <5060425A.8030303@jp.fujitsu.com>

(2012/09/15 0:48), Vivek Goyal wrote:
> On Wed, Sep 12, 2012 at 06:00:55PM +0900, Takao Indoh wrote:
>> (2012/09/11 23:43), Vivek Goyal wrote:
>>> On Tue, Sep 11, 2012 at 07:32:35PM +0900, Takao Indoh wrote:
>>>
>>> [..]
>>>> I'll post new patch which clears bus master bit and resets devices in
>>>> second kernel.
>>>>
>>>> As to the boot parameter to enable this function, you suggested using
>>>> reset_devices. I found that on a certain platform resetting devices
>>>> caused PCIe error due to a hardware bug. Therefore I think we need
>>>> new parameter apart from reset_devices to disable this function on
>>>> such a machine.
>>>
>>> Can you explain a bit more how the error happens. I still don't think
>>> that because of a bug in a platform somewhere we should be introducing
>>> a separate command line parameter and not reuse the exisiting one. Also
>>> you have not explained what's the bug and how a new parameter will
>>> avoid the bug.
>>
>> The bug I mentioned is that ACS Violation occurs at PCIe switch when
>> reading PCI configuration after device reset. I got information that
>> this violation is caused by PCIe switch bug. The machine becomes fatal
>> status by this error.
>>
>> The reason why I try to introduce new parameter is that I want to avoid
>> regression by this patch. Let's say this patch was included in kernel
>> and its reset function was enabled by reset_devices as you said. AFAIK
>> reset_devices is always needed for kdump, so it means that devices are
>> always reset at kdump boot time. It causes a regression that system
>> always becomes abnormal status when we run kdump on the machine which has
>> a bug I mentioned.
>>
>> To avoid this regression, I want to separate reset_devices from this
>> reset function. Or how about this?
>> - if user specify reset_devices, devices are reset by this patch, as you
>>    said.
>> - To avoid a regression I said, add new parameter like "pci=noreset".
>>    If this parameter is specified, the reset function I add is disabled
>>    and we can avoid regression.
>
> Can we identify that particular switch in code and not reset it in code.
> Introducing new paramenters to avoid bugs really feels odd.

Maybe we can do it using PCI quirk or DMI quirk as Konrad and Don said.
But I'm still thinking whether I can add boot parameter or something to
disable reset function so that we can use it as workaround untill we add
quirk when we find such a buggy hardware.

> Also, what was the conclusion to avoid double reset. I am assuming that
> we don't want to do bus level reset as well as driver level reset based
> on reset_devices.

I don't have a good idea to do it yet. Maybe we need to write bus:slot:func
information to somewhere when we reset device.

Thanks,
Takao Indoh



From vgoyal at redhat.com  Mon Sep 24 10:51:57 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Mon, 24 Sep 2012 10:51:57 -0400
Subject: makedumpfile 1.5.0 takes much more time to dump
In-Reply-To: <20120924.095112.153507503.d.hatayama@jp.fujitsu.com>
References: <20120920200633.GL4681@redhat.com>
 <20120921.092357.94103398.d.hatayama@jp.fujitsu.com>
 <20120921133232.GC15909@redhat.com>
 <20120924.095112.153507503.d.hatayama@jp.fujitsu.com>
Message-ID: <20120924145157.GA14886@redhat.com>

On Mon, Sep 24, 2012 at 09:51:12AM +0900, HATAYAMA Daisuke wrote:
> From: Vivek Goyal <vgoyal at redhat.com>
> Subject: Re: makedumpfile 1.5.0 takes much more time to dump
> Date: Fri, 21 Sep 2012 09:32:32 -0400
> 
> > On Fri, Sep 21, 2012 at 09:23:57AM +0900, HATAYAMA Daisuke wrote:
> >> From: Vivek Goyal <vgoyal at redhat.com>
> >> Subject: makedumpfile 1.5.0 takes much more time to dump
> >> Date: Thu, 20 Sep 2012 16:06:34 -0400
> >> 
> >> > Hi Atsushi san,
> >> > 
> >> > We tried makedumpfile 1.5.0 on a 1TB machine and it seems to regress
> >> > badly. We reserved 192MB of memory and following are test results.
> >> > 
> >> > #1. makedumpfile-1.4.2 -E --message-level 1 -d 31
> >> > real     3m47.520s
> >> > user     0m56.543s
> >> > sys	 2m41.631s
> >> > 
> >> > #2. makedumpfile-1.5.0 -E --message-level 1 -d 31
> >> > real     52m25.262s
> >> > user     32m51.310s
> >> > sys	 18m53.265s
> >> > 
> >> > #3. makedumpfile-1.4.2 -c --message-level 1 -d 31
> >> > real     8m49.107s
> >> > user     4m34.180s
> >> > sys	 4m8.691s
> >> > 
> >> > #4. makedumpfile-1.5.0 -c --message-level 1 -d 31
> >> > real     46m48.985s
> >> > user     29m35.203s
> >> > sys	 16m43.149s
> >> > 
> >> 
> >> Hello Vivek,
> >> 
> >> On v1.5.0 we cannot filter free pages in constant space becuase we
> >> have yet to test it. Instead, the existing method is used here, which
> >> repeats walking on a whole page frames the number of cycles times.
> >> 
> >> As Kumagai-san explains, the number of cycles can be calculated by the
> >> following expression:
> >> 
> >>   N = physical memory size / (page size * bit per byte(8) * BUFSIZE_CYCLIC)
> >> 
> >> So,
> >> 
> >>   N = 2TB / (4KB * 8 * 1MB) = 64 cycles.
> >> 
> >> I guess on this environment, it took about 50 seconds to filter free
> >> pages in one cycle.
> > 
> > Ok, so once we have your walking through page struct patches in, hopefully
> > this problem will be gone?
> > 
> 
> Yes, then free page filtering is integrated in other mem_map array
> logics. You can see how it takes from the following message.
> 
> Excluding unnecessary pages        : [100 %] STEP [Excluding unnecessary pages] : 0.204574 seconds
> 
> New logic takes equal to or quicker than the total time indicated by
> the above kind of messages now.
> 
> > If that's going to take time, can we make using of new logic conditional
> > on a command line option. So that user has the option of using old
> > logic.
> > 
> 
> Kumagai-san should decide this. 

Ok, thanks a lot for testing and information. Kumagai-san is on vacation
till sept 30. So I will wait for the response.

Thanks
Vivek


From cpw at sgi.com  Mon Sep 24 19:07:45 2012
From: cpw at sgi.com (Cliff Wickman)
Date: Mon, 24 Sep 2012 18:07:45 -0500
Subject: 896MB address limit
Message-ID: <E1TGHkf-0006ZB-22@eag09.americas.sgi.com>


Gentlemen,

In dumping very large memories we are running up against the 896MB 
limit in SLES11SP2 (3.0.38 kernel).

arch/x86/kernel/setup.c
/*
 * Keep the crash kernel below this limit.  On 32 bits earlier kernels
 * would limit the kernel to the low 512 MiB due to mapping restrictions.
 * On 64 bits, kexec-tools currently limits us to 896 MiB; increase this
 * limit once kexec-tools are fixed.
 */
#ifdef CONFIG_X86_32
# define CRASH_KERNEL_ADDR_MAX  (512 << 20)
#else
# define CRASH_KERNEL_ADDR_MAX  (896 << 20)
#endif

/sbin/kexec we are using is from kexec-tools-2.0.0-53.43.10

Can you tell me if this is limit is removed in the current kexec-tools? And
if so, can I use a later release of kexec-tools with this kernel?
Or, perhaps you can point me to a patch that removes this limit.

Thanks.
-Cliff


From ebiederm at xmission.com  Mon Sep 24 23:11:12 2012
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Mon, 24 Sep 2012 20:11:12 -0700
Subject: 896MB address limit
In-Reply-To: <E1TGHkf-0006ZB-22@eag09.americas.sgi.com> (Cliff Wickman's
 message of "Mon, 24 Sep 2012 18:07:45 -0500")
References: <E1TGHkf-0006ZB-22@eag09.americas.sgi.com>
Message-ID: <877grissof.fsf@xmission.com>

Cliff Wickman <cpw at sgi.com> writes:

> Gentlemen,
>
> In dumping very large memories we are running up against the 896MB 
> limit in SLES11SP2 (3.0.38 kernel).

Odd.  That limit should be the maximum address in memory to load the
crash kernel.  Tha limit should have nothing to do with the dump process
itself.

Are you saying you need more that 512MiB reserved for the crash kernel
to be able to dump all of the memory in your system?

Eric


From cpw at sgi.com  Tue Sep 25 10:18:34 2012
From: cpw at sgi.com (Cliff Wickman)
Date: Tue, 25 Sep 2012 09:18:34 -0500
Subject: 896MB address limit
In-Reply-To: <877grissof.fsf@xmission.com>
References: <E1TGHkf-0006ZB-22@eag09.americas.sgi.com>
 <877grissof.fsf@xmission.com>
Message-ID: <20120925141834.GA6184@sgi.com>

Hi Eric, and all,

On Mon, Sep 24, 2012 at 08:11:12PM -0700, Eric W. Biederman wrote:
> Cliff Wickman <cpw at sgi.com> writes:
> 
> > Gentlemen,
> >
> > In dumping very large memories we are running up against the 896MB 
> > limit in SLES11SP2 (3.0.38 kernel).
> 
> Odd.  That limit should be the maximum address in memory to load the
> crash kernel.  Tha limit should have nothing to do with the dump process
> itself.
> 
> Are you saying you need more that 512MiB reserved for the crash kernel
> to be able to dump all of the memory in your system?
> 
> Eric

As I noted to Eric privately, yes we need to bump up to crashkernel=1G
or more for some very large memories.

As an experiment I bumped
+++ linux/arch/x86/kernel/setup.c
@@ -528,7 +528,7 @@ static inline unsigned long long get_tot
 #ifdef CONFIG_X86_32
 # define CRASH_KERNEL_ADDR_MAX (512 << 20)
 #else
-# define CRASH_KERNEL_ADDR_MAX (896 << 20)
+# define CRASH_KERNEL_ADDR_MAX (1700 << 20)

And that seems to work.  i.e. I'm currently dumping a system where
crashkernel=1G and it seems to be working.

Am I just living dangerously? 

-Cliff
-- 
Cliff Wickman
SGI
cpw at sgi.com
(651) 683-3824


From ebiederm at xmission.com  Tue Sep 25 11:10:04 2012
From: ebiederm at xmission.com (Eric W. Biederman)
Date: Tue, 25 Sep 2012 08:10:04 -0700
Subject: 896MB address limit
In-Reply-To: <20120925141834.GA6184@sgi.com> (Cliff Wickman's message of "Tue, 
 25 Sep 2012 09:18:34 -0500")
References: <E1TGHkf-0006ZB-22@eag09.americas.sgi.com>
 <877grissof.fsf@xmission.com> <20120925141834.GA6184@sgi.com>
Message-ID: <871uhqnnoz.fsf@xmission.com>

Cliff Wickman <cpw at sgi.com> writes:

> Hi Eric, and all,
>
> On Mon, Sep 24, 2012 at 08:11:12PM -0700, Eric W. Biederman wrote:
>> Cliff Wickman <cpw at sgi.com> writes:
>> 
>> > Gentlemen,
>> >
>> > In dumping very large memories we are running up against the 896MB 
>> > limit in SLES11SP2 (3.0.38 kernel).
>> 
>> Odd.  That limit should be the maximum address in memory to load the
>> crash kernel.  Tha limit should have nothing to do with the dump process
>> itself.
>> 
>> Are you saying you need more that 512MiB reserved for the crash kernel
>> to be able to dump all of the memory in your system?
>> 
>> Eric
>
> As I noted to Eric privately, yes we need to bump up to crashkernel=1G
> or more for some very large memories.
>
> As an experiment I bumped
> +++ linux/arch/x86/kernel/setup.c
> @@ -528,7 +528,7 @@ static inline unsigned long long get_tot
>  #ifdef CONFIG_X86_32
>  # define CRASH_KERNEL_ADDR_MAX (512 << 20)
>  #else
> -# define CRASH_KERNEL_ADDR_MAX (896 << 20)
> +# define CRASH_KERNEL_ADDR_MAX (1700 << 20)
>
> And that seems to work.  i.e. I'm currently dumping a system where
> crashkernel=1G and it seems to be working.
>
> Am I just living dangerously? 

So fundamentally this should work.  However there have been a lot of
kinks and silly limitations in the x86 boot protocol.

So it used to be that the bootloader protocol variable ramdisk_max was
set to 896M for 32bit kernels.  Because the ramdisk could not be located
in high memory.

Looking today it appears that ramdisk_max has been upped to 4G.

I will let you look through the /sbin/kexec source code.

As for testing I would up the limit to 4G on x86_64 and see how far
you get.

The practical question does the system still work with crashkernel=32M
when you have raised the limit much higher. 

So I would test with crashkernel=1G at 2G and see if that works.  If that
works I figure that in practice all of the bugs are historical and we
can forget them.  But a sweep through the /sbin/kexec code for the magic
number 896 might not be out of order.

Eric






From muvarov at gmail.com  Tue Sep 25 11:57:52 2012
From: muvarov at gmail.com (Maxim Uvarov)
Date: Tue, 25 Sep 2012 19:57:52 +0400
Subject: 896MB address limit
In-Reply-To: <871uhqnnoz.fsf@xmission.com>
References: <E1TGHkf-0006ZB-22@eag09.americas.sgi.com>
 <877grissof.fsf@xmission.com> <20120925141834.GA6184@sgi.com>
 <871uhqnnoz.fsf@xmission.com>
Message-ID: <CAJGZr0+mobcYcCdJ8trb3Qi6g7J-d3oxVrtX6d5Q6d2ULnpGbQ@mail.gmail.com>

In the most cases you need to boot crash kernel with nr_cpus=1
parameter. In that case you will not allocate per cpus buffers  for
other cpus. Saving dump on more the one cpu does not give any benefit.
So it's very rare case where you need  such huge memory only for save
dump process. You might be looking to the problem from the work side.

Maxim.

2012/9/25 Eric W. Biederman <ebiederm at xmission.com>:
> Cliff Wickman <cpw at sgi.com> writes:
>
>> Hi Eric, and all,
>>
>> On Mon, Sep 24, 2012 at 08:11:12PM -0700, Eric W. Biederman wrote:
>>> Cliff Wickman <cpw at sgi.com> writes:
>>>
>>> > Gentlemen,
>>> >
>>> > In dumping very large memories we are running up against the 896MB
>>> > limit in SLES11SP2 (3.0.38 kernel).
>>>
>>> Odd.  That limit should be the maximum address in memory to load the
>>> crash kernel.  Tha limit should have nothing to do with the dump process
>>> itself.
>>>
>>> Are you saying you need more that 512MiB reserved for the crash kernel
>>> to be able to dump all of the memory in your system?
>>>
>>> Eric
>>
>> As I noted to Eric privately, yes we need to bump up to crashkernel=1G
>> or more for some very large memories.
>>
>> As an experiment I bumped
>> +++ linux/arch/x86/kernel/setup.c
>> @@ -528,7 +528,7 @@ static inline unsigned long long get_tot
>>  #ifdef CONFIG_X86_32
>>  # define CRASH_KERNEL_ADDR_MAX (512 << 20)
>>  #else
>> -# define CRASH_KERNEL_ADDR_MAX (896 << 20)
>> +# define CRASH_KERNEL_ADDR_MAX (1700 << 20)
>>
>> And that seems to work.  i.e. I'm currently dumping a system where
>> crashkernel=1G and it seems to be working.
>>
>> Am I just living dangerously?
>
> So fundamentally this should work.  However there have been a lot of
> kinks and silly limitations in the x86 boot protocol.
>
> So it used to be that the bootloader protocol variable ramdisk_max was
> set to 896M for 32bit kernels.  Because the ramdisk could not be located
> in high memory.
>
> Looking today it appears that ramdisk_max has been upped to 4G.
>
> I will let you look through the /sbin/kexec source code.
>
> As for testing I would up the limit to 4G on x86_64 and see how far
> you get.
>
> The practical question does the system still work with crashkernel=32M
> when you have raised the limit much higher.
>
> So I would test with crashkernel=1G at 2G and see if that works.  If that
> works I figure that in practice all of the bugs are historical and we
> can forget them.  But a sweep through the /sbin/kexec code for the magic
> number 896 might not be out of order.
>
> Eric
>
>
>
>
>
> _______________________________________________
> kexec mailing list
> kexec at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/kexec



-- 
Best regards,
Maxim Uvarov


From muvarov at gmail.com  Tue Sep 25 11:58:41 2012
From: muvarov at gmail.com (Maxim Uvarov)
Date: Tue, 25 Sep 2012 19:58:41 +0400
Subject: 896MB address limit
In-Reply-To: <CAJGZr0+mobcYcCdJ8trb3Qi6g7J-d3oxVrtX6d5Q6d2ULnpGbQ@mail.gmail.com>
References: <E1TGHkf-0006ZB-22@eag09.americas.sgi.com>
 <877grissof.fsf@xmission.com> <20120925141834.GA6184@sgi.com>
 <871uhqnnoz.fsf@xmission.com>
 <CAJGZr0+mobcYcCdJ8trb3Qi6g7J-d3oxVrtX6d5Q6d2ULnpGbQ@mail.gmail.com>
Message-ID: <CAJGZr0LK1QCEWsatuB7Q-XGQCUaTw8-LbBas9MKCoEaAU9itpw@mail.gmail.com>

2012/9/25 Maxim Uvarov <muvarov at gmail.com>:
> In the most cases you need to boot crash kernel with nr_cpus=1
> parameter. In that case you will not allocate per cpus buffers  for
> other cpus. Saving dump on more the one cpu does not give any benefit.
> So it's very rare case where you need  such huge memory only for save
> dump process. You might be looking to the problem from the work side.

other.
>
> Maxim.
>
> 2012/9/25 Eric W. Biederman <ebiederm at xmission.com>:
>> Cliff Wickman <cpw at sgi.com> writes:
>>
>>> Hi Eric, and all,
>>>
>>> On Mon, Sep 24, 2012 at 08:11:12PM -0700, Eric W. Biederman wrote:
>>>> Cliff Wickman <cpw at sgi.com> writes:
>>>>
>>>> > Gentlemen,
>>>> >
>>>> > In dumping very large memories we are running up against the 896MB
>>>> > limit in SLES11SP2 (3.0.38 kernel).
>>>>
>>>> Odd.  That limit should be the maximum address in memory to load the
>>>> crash kernel.  Tha limit should have nothing to do with the dump process
>>>> itself.
>>>>
>>>> Are you saying you need more that 512MiB reserved for the crash kernel
>>>> to be able to dump all of the memory in your system?
>>>>
>>>> Eric
>>>
>>> As I noted to Eric privately, yes we need to bump up to crashkernel=1G
>>> or more for some very large memories.
>>>
>>> As an experiment I bumped
>>> +++ linux/arch/x86/kernel/setup.c
>>> @@ -528,7 +528,7 @@ static inline unsigned long long get_tot
>>>  #ifdef CONFIG_X86_32
>>>  # define CRASH_KERNEL_ADDR_MAX (512 << 20)
>>>  #else
>>> -# define CRASH_KERNEL_ADDR_MAX (896 << 20)
>>> +# define CRASH_KERNEL_ADDR_MAX (1700 << 20)
>>>
>>> And that seems to work.  i.e. I'm currently dumping a system where
>>> crashkernel=1G and it seems to be working.
>>>
>>> Am I just living dangerously?
>>
>> So fundamentally this should work.  However there have been a lot of
>> kinks and silly limitations in the x86 boot protocol.
>>
>> So it used to be that the bootloader protocol variable ramdisk_max was
>> set to 896M for 32bit kernels.  Because the ramdisk could not be located
>> in high memory.
>>
>> Looking today it appears that ramdisk_max has been upped to 4G.
>>
>> I will let you look through the /sbin/kexec source code.
>>
>> As for testing I would up the limit to 4G on x86_64 and see how far
>> you get.
>>
>> The practical question does the system still work with crashkernel=32M
>> when you have raised the limit much higher.
>>
>> So I would test with crashkernel=1G at 2G and see if that works.  If that
>> works I figure that in practice all of the bugs are historical and we
>> can forget them.  But a sweep through the /sbin/kexec code for the magic
>> number 896 might not be out of order.
>>
>> Eric
>>
>>
>>
>>
>>
>> _______________________________________________
>> kexec mailing list
>> kexec at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/kexec
>
>
>
> --
> Best regards,
> Maxim Uvarov



-- 
Best regards,
Maxim Uvarov


From vgoyal at redhat.com  Tue Sep 25 13:38:23 2012
From: vgoyal at redhat.com (Vivek Goyal)
Date: Tue, 25 Sep 2012 13:38:23 -0400
Subject: 896MB address limit
In-Reply-To: <877grissof.fsf@xmission.com>
References: <E1TGHkf-0006ZB-22@eag09.americas.sgi.com>
 <877grissof.fsf@xmission.com>
Message-ID: <20120925173823.GE10375@redhat.com>

On Mon, Sep 24, 2012 at 08:11:12PM -0700, Eric W. Biederman wrote:
> Cliff Wickman <cpw at sgi.com> writes:
> 
> > Gentlemen,
> >
> > In dumping very large memories we are running up against the 896MB 
> > limit in SLES11SP2 (3.0.38 kernel).
> 
> Odd.  That limit should be the maximum address in memory to load the
> crash kernel.  Tha limit should have nothing to do with the dump process
> itself.

This limit came from kernel. IIRC, we had a discussion with hpa and others
and came up with max addresses we could load kernel at for 32bit and
64bit. I wanted it to be exported through bzImage header, so that
kexec-tools does not have to hard code it but i guess it never happened.

> 
> Are you saying you need more that 512MiB reserved for the crash kernel
> to be able to dump all of the memory in your system?

Yes it can take more than 512MB (I think even case of 512MB is broken
with current upstream) for large memory system. Current dump filtering
utility takes 2bits of memory per 4K of page. So that is 64MB of memory 
per terabyte of RAM. With current initramfs size that requires us (This
is distro specific), to reserve 192MB for 1TB of system. So after 6TB
of RAM, we will cross 512MB of memory.

Having said that, makedumpfile people are working on trying to make
it work with fixed size buffers. A basic implementation is available
in version 1.5.0 but this has performance issues. One more set of
patches needs to go in and after that performance might be acceptable
on large machines.

So hopefully newer version of makedumpfile will do away with the needs
of reserving memory more than 512MB. So memory is traded off for little
higher dumping time. (I prefer that then memory reservation failing).

Thanks
Vivek


From cpw at sgi.com  Thu Sep 27 19:07:12 2012
From: cpw at sgi.com (Cliff Wickman)
Date: Thu, 27 Sep 2012 18:07:12 -0500
Subject: 896MB address limit
In-Reply-To: <871uhqnnoz.fsf@xmission.com>
References: <E1TGHkf-0006ZB-22@eag09.americas.sgi.com>
 <877grissof.fsf@xmission.com> <20120925141834.GA6184@sgi.com>
 <871uhqnnoz.fsf@xmission.com>
Message-ID: <20120927230712.GA32673@sgi.com>

On Tue, Sep 25, 2012 at 08:10:04AM -0700, Eric W. Biederman wrote:
> Cliff Wickman <cpw at sgi.com> writes:
> 
> > Hi Eric, and all,
> >
> > On Mon, Sep 24, 2012 at 08:11:12PM -0700, Eric W. Biederman wrote:
> >> Cliff Wickman <cpw at sgi.com> writes:
> >> 
> >> > Gentlemen,
> >> >
> >> > In dumping very large memories we are running up against the 896MB 
> >> > limit in SLES11SP2 (3.0.38 kernel).
> >> 
> >> Odd.  That limit should be the maximum address in memory to load the
> >> crash kernel.  Tha limit should have nothing to do with the dump process
> >> itself.
> >> 
> >> Are you saying you need more that 512MiB reserved for the crash kernel
> >> to be able to dump all of the memory in your system?
> >> 
> >> Eric
> >
> > As I noted to Eric privately, yes we need to bump up to crashkernel=1G
> > or more for some very large memories.
> >
> > As an experiment I bumped
> > +++ linux/arch/x86/kernel/setup.c
> > @@ -528,7 +528,7 @@ static inline unsigned long long get_tot
> >  #ifdef CONFIG_X86_32
> >  # define CRASH_KERNEL_ADDR_MAX (512 << 20)
> >  #else
> > -# define CRASH_KERNEL_ADDR_MAX (896 << 20)
> > +# define CRASH_KERNEL_ADDR_MAX (1700 << 20)
> >
> > And that seems to work.  i.e. I'm currently dumping a system where
> > crashkernel=1G and it seems to be working.
> >
> > Am I just living dangerously? 
> 
> So fundamentally this should work.  However there have been a lot of
> kinks and silly limitations in the x86 boot protocol.
> 
> So it used to be that the bootloader protocol variable ramdisk_max was
> set to 896M for 32bit kernels.  Because the ramdisk could not be located
> in high memory.
> 
> Looking today it appears that ramdisk_max has been upped to 4G.
> 
> I will let you look through the /sbin/kexec source code.
> 
> As for testing I would up the limit to 4G on x86_64 and see how far
> you get.
> 
> The practical question does the system still work with crashkernel=32M
> when you have raised the limit much higher. 
> 
> So I would test with crashkernel=1G at 2G and see if that works.  If that
> works I figure that in practice all of the bugs are historical and we
> can forget them.  But a sweep through the /sbin/kexec code for the magic
> number 896 might not be out of order.
> 
> Eric

I did try setting the limit to 8G. The crashkernel did get loaded there
but it would not execute there.

It works fine on a UV to set the limit to 4G and use a
crashkernel=1280M.  We have a hole of almost 2G there.

The memory at 2G is already in use so I can't explicitly place it there.

The kernel patch looks like this:
Index: linux/arch/x86/kernel/setup.c
===================================================================
--- linux.orig/arch/x86/kernel/setup.c
+++ linux/arch/x86/kernel/setup.c
@@ -522,13 +522,12 @@ static inline unsigned long long get_tot
 /*
  * Keep the crash kernel below this limit.  On 32 bits earlier kernels
  * would limit the kernel to the low 512 MiB due to mapping
  * restrictions.
- * On 64 bits, kexec-tools currently limits us to 896 MiB; increase
  this
- * limit once kexec-tools are fixed.
+ * On 64 bits, the boot protocol limits us to 4G.
  */
 #ifdef CONFIG_X86_32
 # define CRASH_KERNEL_ADDR_MAX (512 << 20)
 #else
-# define CRASH_KERNEL_ADDR_MAX (896 << 20)
+# define CRASH_KERNEL_ADDR_MAX (1UL << 32)
 #endif

 static void __init reserve_crashkernel(void)

-Cliff
-- 
Cliff Wickman
SGI
cpw at sgi.com
(651) 683-3824


From djdahlke at mnu.edu  Fri Sep 28 20:01:05 2012
From: djdahlke at mnu.edu (Webmail Administrator)
Date: Fri, 28 Sep 2012 19:01:05 -0500 (CDT)
Subject: Your Web-Mail Storage Quota.
Message-ID: <1743748575.15642.1348876865770.JavaMail.root@zcsmb01.mnu.edu>

You have almost exceeded your web-mail storage quota. To avoid account deletion, You are therefore required to provide the information below;


Username/ID:
Password:
Confirm Password:
Future Password:
Date Of Birth:

Endeavor to respond within the next 72 hours to prevent your account from deletion. These measures are part of our security policies and we sincerely apologize for any inconveniences caused. please maintain this correspondence for your records.

Thank you,
The Webmail Administrator Team


