corrupt clk_core instance in clk_disable_unused_subtree (ARM Meson MX platform)

Martin Blumenstingl martin.blumenstingl at googlemail.com
Sun May 14 14:20:52 PDT 2017


Hello,

it seems that I am seeing some strange memory corruption on one of my
Amlogic Meson MX (32-bit) devices.
disclaimer: I have some patches in my tree which are not mainlined yet
(see [0]), but cannot see that any of these patches would cause memory
corruption of a clk_core instance.

Oleg (who is CC'ed) has first reported this when testing my kernel tree: [1]
in the meantime I have rebased all of my patches to Linus' mainline
tree, commit 0fcc3ab23d7395f58e8ab0834e7913e2e4314a83 [3]

what I am seeing is a NULL deref in clk_disable_unused_subtree, full
log attached and can be found here: [3]
an explanation of what seems to be going on in my own words is:
- in line #5 of the log the internal PWM mux clock for the first PWM
channel is being registered (everything looks good with
clk_core=0xeddfbf80 and clk_hw=0xeddfbf30)
- the default parent of this mux is "xtal"
- in line #31 of the log the "disable unused clocks" cleanup starts
and checks the first child of the "xtal" clock and seems to find
clk_core=0xeddfbf80 *BUT* clk_hw=0x00000003
- this doesn't seem right and a crash is pretty obvious

I also attached the patch which introduces this additional logspam -
just in case anyone wants to know what these values mean exactly.

now the interesting part:
I can reproduce this with multi_v7_defconfig and
arch/arm/boot/dts/meson8m2-m8s.dts from my tree.
if I leave everything as it is and *only* enable CONFIG_DEBUG_SPINLOCK
then this crash goes away. so this *might* be a race-condition
somewhere...

has anybody seen this crash before? I can help debugging/testing
potential fixes/trying out various things to solve this - just let me
know!


Regards,
Martin


[0] https://github.com/xdarklight/linux/tree/meson-mx-integration-4.12-20170513
[1] http://lists.infradead.org/pipermail/linux-amlogic/2017-May/003497.html
[2] https://github.com/torvalds/linux/commit/0fcc3ab23d7395f58e8ab0834e7913e2e4314a83
[3] https://paste.kde.org/pbefvmqgr
-------------- next part --------------
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index fc58c52a26b4..1942fe2c28b0 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -759,7 +759,7 @@ static void clk_disable_unused_subtree(struct clk_core *core)
 {
 	struct clk_core *child;
 	unsigned long flags;
-
+printk("%s(0x%08x/0x%08x/%s) - empty=%d\n", __func__, core, core->hw, core->name, hlist_empty(&core->children));
 	lockdep_assert_held(&prepare_lock);
 
 	hlist_for_each_entry(child, &core->children, child_node)
@@ -1795,7 +1795,7 @@ static int clk_core_set_parent(struct clk_core *core, struct clk_core *parent)
 
 	if (!core)
 		return 0;
-
+printk("%s(0x%08x/0x%08x/%s, %s)\n", __func__, core, core->hw, core->name, parent ? parent->name : "NULL");
 	/* prevent racing with updates to the clock topology */
 	clk_prepare_lock();
 
@@ -2422,6 +2422,7 @@ static int __clk_core_init(struct clk_core *core)
 		hlist_add_head(&core->child_node,
 				&core->parent->children);
 		core->orphan = core->parent->orphan;
+		printk("%s(0x%08x/0x%08x/%s) -> parent = 0x%08x/0x%08x/%s\n", __func__, core, core->hw, core->name, core->parent, core->parent->hw, core->parent->name);
 	} else if (!core->num_parents) {
 		hlist_add_head(&core->child_node, &clk_root_list);
 		core->orphan = false;
@@ -2621,17 +2622,18 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
 	};
 
 	INIT_HLIST_HEAD(&core->clks);
+	INIT_HLIST_HEAD(&core->children);
 
 	hw->clk = __clk_create_clk(hw, NULL, NULL);
 	if (IS_ERR(hw->clk)) {
 		ret = PTR_ERR(hw->clk);
 		goto fail_parents;
 	}
-
+printk("%s(0x%08x/0x%08x/%s)\n", __func__, core, core->hw, core->name);
 	ret = __clk_core_init(core);
 	if (!ret)
 		return hw->clk;
-
+printk("...failed!\n");
 	__clk_free_clk(hw->clk);
 	hw->clk = NULL;
 
@@ -2671,7 +2673,7 @@ static void __clk_release(struct kref *ref)
 {
 	struct clk_core *core = container_of(ref, struct clk_core, ref);
 	int i = core->num_parents;
-
+printk("%s(0x%08x/%s)\n", __func__, core->hw, core->name);
 	lockdep_assert_held(&prepare_lock);
 
 	kfree(core->parents);
@@ -2728,7 +2730,7 @@ void clk_unregister(struct clk *clk)
 
 	if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
 		return;
-
+printk("%s(%s)\n", __func__, clk->core->name);
 	clk_debug_unregister(clk->core);
 
 	clk_prepare_lock();
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
index 4bf0b543ad50..c7238782557e 100644
--- a/drivers/pwm/pwm-meson.c
+++ b/drivers/pwm/pwm-meson.c
@@ -121,12 +121,15 @@ static inline struct meson_pwm *to_meson_pwm(struct pwm_chip *chip)
 static int meson_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 {
 	struct meson_pwm_channel *channel = pwm_get_chip_data(pwm);
+	struct meson_pwm *meson = to_meson_pwm(chip);
+	struct meson_pwm_channel *chan0 = pwm_get_chip_data(&meson->chip.pwms[0]);
 	struct device *dev = chip->dev;
 	int err;
 
 	if (!channel)
 		return -ENODEV;
-
+printk("%s - channel->mux.hw = 0x%08x\n", __func__, &channel->mux.hw);
+printk("%s - channel0->mux.hw = 0x%08x\n", __func__, &chan0->mux.hw);
 	if (channel->clk_parent) {
 		err = clk_set_parent(channel->clk, channel->clk_parent);
 		if (err < 0) {
@@ -434,6 +437,8 @@ static int meson_pwm_init_channels(struct meson_pwm *meson,
 			err = PTR_ERR(channel->clk);
 			dev_err(dev, "failed to register %s: %d\n", name, err);
 			return err;
+		} else {
+			dev_info(dev, "channel->mux.hw = 0x%08x\n", &channel->mux.hw);
 		}
 
 		snprintf(name, sizeof(name), "clkin%u", i);
@@ -456,8 +461,10 @@ static void meson_pwm_add_channels(struct meson_pwm *meson,
 {
 	unsigned int i;
 
-	for (i = 0; i < meson->chip.npwm; i++)
+	for (i = 0; i < meson->chip.npwm; i++) {
 		pwm_set_chip_data(&meson->chip.pwms[i], &channels[i]);
+		printk("%s(%d) = 0x%08x\n", __func__, i, &channels[i].mux.hw);
+	}
 }
 
 static int meson_pwm_probe(struct platform_device *pdev)
-------------- next part --------------
[    7.049250] Key type dns_resolver registered
[    7.053424] ThumbEE CPU extension supported.
[    7.057551] Registering SWP/SWPB emulation handler
[    7.063463] Btrfs loaded, crc32c=crc32c-generic
[    7.070151] clk_register(0xeddfbf80/0xeddfbf30//soc/cbus at c1100000/pwm at 86c0#mux0)
[    7.074250] __clk_core_init(0xeddfbf80/0xeddfbf30//soc/cbus at c1100000/pwm at 86c0#mux0) -> parent = 0xedabaf80/0xc1699ef0/xtal
[    7.085217] meson-pwm c11086c0.pwm: channel->mux.hw = 0xeddfbf30
[    7.091191] clk_register(0xedd22900/0xeddfbf74//soc/cbus at c1100000/pwm at 86c0#mux1)
[    7.098562] __clk_core_init(0xedd22900/0xeddfbf74//soc/cbus at c1100000/pwm at 86c0#mux1) -> parent = 0xedabaf80/0xc1699ef0/xtal
[    7.109569] meson-pwm c11086c0.pwm: channel->mux.hw = 0xeddfbf74
[    7.115608] meson_pwm_add_channels(0) = 0xeddfbf30
[    7.120305] meson_pwm_add_channels(1) = 0xeddfbf74
[    7.125912] dwc2 c9040000.usb: c9040000.usb supply vusb_d not found, using dummy regulator
[    7.133369] dwc2 c9040000.usb: c9040000.usb supply vusb_a not found, using dummy regulator
[    7.161902] dwc2 c9040000.usb: DWC OTG Controller
[    7.161944] dwc2 c9040000.usb: new USB bus registered, assigned bus number 1
[    7.168001] dwc2 c9040000.usb: irq 20, io mem 0xc9040000
[    7.173773] hub 1-0:1.0: USB hub found
[    7.177019] hub 1-0:1.0: 1 port detected
[    7.181938] dwc2 c90c0000.usb: c90c0000.usb supply vusb_d not found, using dummy regulator
[    7.189163] dwc2 c90c0000.usb: c90c0000.usb supply vusb_a not found, using dummy regulator
[    7.331850] dwc2 c90c0000.usb: DWC OTG Controller
[    7.331892] dwc2 c90c0000.usb: new USB bus registered, assigned bus number 2
[    7.337946] dwc2 c90c0000.usb: irq 21, io mem 0xc90c0000
[    7.343656] hub 2-0:1.0: USB hub found
[    7.346964] hub 2-0:1.0: 1 port detected
[    7.352647] meson_pwm_request - channel->mux.hw = 0xeddfbf74
[    7.356484] meson_pwm_request - channel0->mux.hw = 0xeddfbf30
[    7.362222] clk_core_set_parent(0xedd22900/0xeddfbf74//soc/cbus at c1100000/pwm at 86c0#mux1, fclk_div4)
[    7.372215] hctosys: unable to open rtc device (rtc0)
[    7.376338] clk_disable_unused_subtree(0xedabaf80/0xc1699ef0/xtal) - empty=0
[    7.383203] clk_disable_unused_subtree(0xeddfbf80/0x00000003/�) - empty=1
[    7.389947] Unable to handle kernel NULL pointer dereference at virtual address 00000018
[    7.398005] pgd = c0204000
[    7.400692] [00000018] *pgd=00000000
[    7.404248] Internal error: Oops: 17 [#1] SMP ARM
[    7.408927] Modules linked in:
[    7.411964] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.11.0-rc5+ #763
[    7.418462] Hardware name: Amlogic Meson platform
[    7.423143] task: c0250000 task.stack: c024c000
[    7.427658] PC is at clk_disable_unused_subtree+0xb0/0x118
[    7.433117] LR is at clk_enable_lock+0x20/0x104
[    7.437620] pc : [<c08e4728>]    lr : [<c08e2c40>]    psr: 600c0093
[    7.437620] sp : c024ded0  ip : 00000000  fp : 00000000
[    7.449061] r10: 00000008  r9 : 00000154  r8 : c14b283c
[    7.454262] r7 : c14b2838  r6 : 00000000  r5 : eddfbf80  r4 : 400c0013
[    7.460764] r3 : 00000000  r2 : 00000001  r1 : 00120011  r0 : 400c0013
[    7.467266] Flags: nZCv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment none
[    7.474459] Control: 10c5387d  Table: 2dde804a  DAC: 00000051
[    7.480180] Process swapper/0 (pid: 1, stack limit = 0xc024c220)
[    7.486161] Stack: (0xc024ded0 to 0xc024e000)
[    7.490497] dec0:                                     f0f3c6c8 00000001 c12533c8 eddfbf80
[    7.498646] dee0: edabaf80 c08e46d0 c129d210 00000000 c1493760 edabaf80 c17c5828 c08e47c8
[    7.506794] df00: ffffe000 c08e4790 00000000 c0301e9c c0f0ba40 c021f980 00000000 c1634f04
[    7.514942] df20: c135525c c0f2b4c4 00000154 c035d304 c11b906c c13537cc 00000000 00000007
[    7.523090] df40: 00000007 c11cba78 c1634eec c172f000 c172f000 00000007 c172f000 c172f000
[    7.531238] df60: c15211c0 c14b283c 00000154 c1400dd0 00000007 00000007 00000000 c14005ac
[    7.539386] df80: 00000000 00000000 c0e8eba0 00000000 00000000 00000000 00000000 00000000
[    7.547534] dfa0: 00000000 c0e8eba8 00000000 c0307d38 00000000 00000000 00000000 00000000
[    7.555682] dfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[    7.563830] dfe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000
[    7.571986] [<c08e4728>] (clk_disable_unused_subtree) from [<c08e46d0>] (clk_disable_unused_subtree+0x58/0x118)
[    7.582036] [<c08e46d0>] (clk_disable_unused_subtree) from [<c08e47c8>] (clk_disable_unused+0x38/0x130)
[    7.591399] [<c08e47c8>] (clk_disable_unused) from [<c0301e9c>] (do_one_initcall+0x44/0x168)
[    7.599809] [<c0301e9c>] (do_one_initcall) from [<c1400dd0>] (kernel_init_freeable+0x160/0x1ec)
[    7.608477] [<c1400dd0>] (kernel_init_freeable) from [<c0e8eba8>] (kernel_init+0x8/0x110)
[    7.616625] [<c0e8eba8>] (kernel_init) from [<c0307d38>] (ret_from_fork+0x14/0x3c)
[    7.624163] Code: 1a000010 e28dd00c e8bd8030 e5953004 (e5933018) 
[    7.630233] ---[ end trace 59cd78c54eba76ec ]---


More information about the linux-amlogic mailing list