[PATCH] pseries/drmem: Check for zero filled ibm, dynamic-memory property.

Cyril Bur cyrilbur at gmail.com
Fri Feb 16 15:17:34 AEDT 2018


On Thu, 2018-02-15 at 21:27 -0600, Nathan Fontenot wrote:
> Some versions of QEMU will produce an ibm,dynamic-reconfiguration-memory
> node with a ibm,dynamic-memory property that is zero-filled. This causes
> the drmem code to oops trying to parse this property.
> 
> The fix for this is to validate that the property does contain LMB
> entries before trying to parse it and bail if the count is zero.
> 
> Oops: Kernel access of bad area, sig: 11 [#1]
> SMP NR_CPUS=2048
> NUMA
> pSeries
> Modules linked in:
> Supported: Yes
> CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.12.14-11.2-default #1
> task: c00000007e639680 task.stack: c00000007e648000
> NIP: c000000000c709a4 LR: c000000000c70998 CTR: 0000000000000000
> REGS: c00000007e64b8d0 TRAP: 0300   Not tainted  (4.12.14-11.2-default)
> MSR: 800000010280b033 <SF,VEC,VSX,EE,FP,ME,IR,DR,RI,LE,TM[E]>
>   CR: 84000248  XER: 00000000
> CFAR: c00000000067018c DAR: 0000000000000010 DSISR: 42000000 SOFTE: 1
> GPR00: c000000000c70998 c00000007e64bb50 c000000001157b00 0000000000000000
> GPR04: c00000007e64bb70 0000000000000000 000000000000002f 0000000000000022
> GPR08: 0000000000000003 c000000006f63fac c000000006f63fb0 000000000000001e
> GPR12: 0000000000000000 c00000000fa80000 c00000000000dca8 0000000000000000
> GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> GPR20: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
> GPR24: c000000000cccb98 c000000000c636f0 c000000000c56cd0 0000000000000007
> GPR28: c000000000cccba8 c00000007ffffc30 c00000007e64bbf0 0000000000000010
> NIP [c000000000c709a4] read_drconf_v1_cell+0x54/0x9c
> LR [c000000000c70998] read_drconf_v1_cell+0x48/0x9c
> Call Trace:
> [c00000007e64bb50] [c000000000c56cd0] __param_initcall_debug+0x0/0x28 (unreliable)
> [c00000007e64bb90] [c000000000c70e24] drmem_init+0x144/0x2f8
> [c00000007e64bc40] [c00000000000d034] do_one_initcall+0x64/0x1d0
> [c00000007e64bd00] [c000000000c643d0] kernel_init_freeable+0x298/0x38c
> [c00000007e64bdc0] [c00000000000dcc4] kernel_init+0x24/0x160
> [c00000007e64be30] [c00000000000b428] ret_from_kernel_thread+0x5c/0xb4
> Instruction dump:
> 7c9e2378 60000000 e9429050 e93e0000 7c240b78 7c7f1b78 f9240021 e86a0002
> 4804e41d 60000000 e9210020 39490004 <f87f0000> f9410020 39490010 7d004c2c
> 
> The ibm,dynamic-reconfiguration-memory device tree property
> generated that causes this:
> 
> ibm,dynamic-reconfiguration-memory {
>         ibm,lmb-size = <0x0 0x10000000>;
>         ibm,memory-flags-mask = <0xff>;
>         ibm,dynamic-memory = <0x0 0x0 0x0 0x0 0x0 0x0>;
>         linux,phandle = <0x7e57eed8>;
>         ibm,associativity-lookup-arrays = <0x1 0x4 0x0 0x0 0x0 0x0>;
>         ibm,memory-preservation-time = <0x0>;
> };
> 
> Signed-off-by: Nathan Fontenot <nfont at linux.vnet.ibm.com>

Works for me.

Reviewed-by: Cyril Bur <cyrilbur at gmail.com>

> ---
>  arch/powerpc/mm/drmem.c |    8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/arch/powerpc/mm/drmem.c b/arch/powerpc/mm/drmem.c
> index 1604110c4238..916844f99c64 100644
> --- a/arch/powerpc/mm/drmem.c
> +++ b/arch/powerpc/mm/drmem.c
> @@ -216,6 +216,8 @@ static void __init __walk_drmem_v1_lmbs(const __be32 *prop, const __be32 *usm,
>  	u32 i, n_lmbs;
>  
>  	n_lmbs = of_read_number(prop++, 1);
> +	if (n_lmbs == 0)
> +		return;
>  
>  	for (i = 0; i < n_lmbs; i++) {
>  		read_drconf_v1_cell(&lmb, &prop);
> @@ -245,6 +247,8 @@ static void __init __walk_drmem_v2_lmbs(const __be32 *prop, const __be32 *usm,
>  	u32 i, j, lmb_sets;
>  
>  	lmb_sets = of_read_number(prop++, 1);
> +	if (lmb_sets == 0)
> +		return;
>  
>  	for (i = 0; i < lmb_sets; i++) {
>  		read_drconf_v2_cell(&dr_cell, &prop);
> @@ -354,6 +358,8 @@ static void __init init_drmem_v1_lmbs(const __be32 *prop)
>  	struct drmem_lmb *lmb;
>  
>  	drmem_info->n_lmbs = of_read_number(prop++, 1);
> +	if (drmem_info->n_lmbs == 0)
> +		return;
>  
>  	drmem_info->lmbs = kcalloc(drmem_info->n_lmbs, sizeof(*lmb),
>  				   GFP_KERNEL);
> @@ -373,6 +379,8 @@ static void __init init_drmem_v2_lmbs(const __be32 *prop)
>  	int lmb_index;
>  
>  	lmb_sets = of_read_number(prop++, 1);
> +	if (lmb_sets == 0)
> +		return;
>  
>  	/* first pass, calculate the number of LMBs */
>  	p = prop;
> 


More information about the Linuxppc-dev mailing list