[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