The coreboot_table driver registers a coreboot bus while probing a "coreboot_table" device representing the coreboot table memory region. Probing this device (i.e., registering the bus) is a dependency for the module_init() functions of any driver for this bus (e.g., memconsole-coreboot.c / memconsole_driver_init()).
With synchronous probe, this dependency works OK, as the link order in the Makefile ensures coreboot_table_driver_init() (and thus, coreboot_table_probe()) completes before a coreboot device driver tries to add itself to the bus.
With asynchronous probe, however, coreboot_table_probe() may race with memconsole_driver_init(), and so we're liable to hit one of these two:
1. coreboot_driver_register() eventually hits "[...] the bus was not initialized.", and the memconsole driver fails to register; or 2. coreboot_driver_register() gets past #1, but still races with bus_register() and hits some other undefined/crashing behavior (e.g., in driver_find() [1])
We can resolve this by registering the bus in our initcall, and only deferring "device" work (scanning the coreboot memory region and creating sub-devices) to probe().
[1] Example failure, using 'driver_async_probe=*' kernel command line:
[ 0.114217] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010 ... [ 0.114307] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.1.0-rc1 #63 [ 0.114316] Hardware name: Google Scarlet (DT) ... [ 0.114488] Call trace: [ 0.114494] _raw_spin_lock+0x34/0x60 [ 0.114502] kset_find_obj+0x28/0x84 [ 0.114511] driver_find+0x30/0x50 [ 0.114520] driver_register+0x64/0x10c [ 0.114528] coreboot_driver_register+0x30/0x3c [ 0.114540] memconsole_driver_init+0x24/0x30 [ 0.114550] do_one_initcall+0x154/0x2e0 [ 0.114560] do_initcall_level+0x134/0x160 [ 0.114571] do_initcalls+0x60/0xa0 [ 0.114579] do_basic_setup+0x28/0x34 [ 0.114588] kernel_init_freeable+0xf8/0x150 [ 0.114596] kernel_init+0x2c/0x12c [ 0.114607] ret_from_fork+0x10/0x20 [ 0.114624] Code: 5280002b 1100054a b900092a f9800011 (885ffc01) [ 0.114631] ---[ end trace 0000000000000000 ]---
Fixes: b81e3140e412 ("firmware: coreboot: Make bus registration symmetric") Cc: stable@vger.kernel.org Signed-off-by: Brian Norris briannorris@chromium.org --- Currently, get_maintainers.pl tells me Greg should pick this up. But I CC the chrome-platform list too, since it seems reasonable for Google folks (probably ChromeOS folks are most active here?) to maintain Google/Chrome drivers.
Let me know if y'all would like this official, and I'll push out a MAINTAINERS patch.
drivers/firmware/google/coreboot_table.c | 37 +++++++++++++++++++----- 1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c index c52bcaa9def6..9ca21feb9d45 100644 --- a/drivers/firmware/google/coreboot_table.c +++ b/drivers/firmware/google/coreboot_table.c @@ -149,12 +149,8 @@ static int coreboot_table_probe(struct platform_device *pdev) if (!ptr) return -ENOMEM;
- ret = bus_register(&coreboot_bus_type); - if (!ret) { - ret = coreboot_table_populate(dev, ptr); - if (ret) - bus_unregister(&coreboot_bus_type); - } + ret = coreboot_table_populate(dev, ptr); + memunmap(ptr);
return ret; @@ -169,7 +165,6 @@ static int __cb_dev_unregister(struct device *dev, void *dummy) static int coreboot_table_remove(struct platform_device *pdev) { bus_for_each_dev(&coreboot_bus_type, NULL, NULL, __cb_dev_unregister); - bus_unregister(&coreboot_bus_type); return 0; }
@@ -199,6 +194,32 @@ static struct platform_driver coreboot_table_driver = { .of_match_table = of_match_ptr(coreboot_of_match), }, }; -module_platform_driver(coreboot_table_driver); + +static int __init coreboot_table_driver_init(void) +{ + int ret; + + ret = bus_register(&coreboot_bus_type); + if (ret) + return ret; + + ret = platform_driver_register(&coreboot_table_driver); + if (ret) { + bus_unregister(&coreboot_bus_type); + return ret; + } + + return 0; +} + +static void __exit coreboot_table_driver_exit(void) +{ + platform_driver_unregister(&coreboot_table_driver); + bus_unregister(&coreboot_bus_type); +} + +module_init(coreboot_table_driver_init); +module_exit(coreboot_table_driver_exit); + MODULE_AUTHOR("Google, Inc."); MODULE_LICENSE("GPL");
On 10/19/22 18:10, Brian Norris wrote:
The coreboot_table driver registers a coreboot bus while probing a "coreboot_table" device representing the coreboot table memory region. Probing this device (i.e., registering the bus) is a dependency for the module_init() functions of any driver for this bus (e.g., memconsole-coreboot.c / memconsole_driver_init()).
With synchronous probe, this dependency works OK, as the link order in the Makefile ensures coreboot_table_driver_init() (and thus, coreboot_table_probe()) completes before a coreboot device driver tries to add itself to the bus.
With asynchronous probe, however, coreboot_table_probe() may race with memconsole_driver_init(), and so we're liable to hit one of these two:
- coreboot_driver_register() eventually hits "[...] the bus was not initialized.", and the memconsole driver fails to register; or
- coreboot_driver_register() gets past #1, but still races with bus_register() and hits some other undefined/crashing behavior (e.g., in driver_find() [1])
We can resolve this by registering the bus in our initcall, and only deferring "device" work (scanning the coreboot memory region and creating sub-devices) to probe().
[1] Example failure, using 'driver_async_probe=*' kernel command line:
[ 0.114217] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010 ... [ 0.114307] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 6.1.0-rc1 #63 [ 0.114316] Hardware name: Google Scarlet (DT) ... [ 0.114488] Call trace: [ 0.114494] _raw_spin_lock+0x34/0x60 [ 0.114502] kset_find_obj+0x28/0x84 [ 0.114511] driver_find+0x30/0x50 [ 0.114520] driver_register+0x64/0x10c [ 0.114528] coreboot_driver_register+0x30/0x3c [ 0.114540] memconsole_driver_init+0x24/0x30 [ 0.114550] do_one_initcall+0x154/0x2e0 [ 0.114560] do_initcall_level+0x134/0x160 [ 0.114571] do_initcalls+0x60/0xa0 [ 0.114579] do_basic_setup+0x28/0x34 [ 0.114588] kernel_init_freeable+0xf8/0x150 [ 0.114596] kernel_init+0x2c/0x12c [ 0.114607] ret_from_fork+0x10/0x20 [ 0.114624] Code: 5280002b 1100054a b900092a f9800011 (885ffc01) [ 0.114631] ---[ end trace 0000000000000000 ]---
Fixes: b81e3140e412 ("firmware: coreboot: Make bus registration symmetric") Cc: stable@vger.kernel.org Signed-off-by: Brian Norris briannorris@chromium.org
Reviewed-by: Guenter Roeck linux@roeck-us.net
Currently, get_maintainers.pl tells me Greg should pick this up. But I CC the chrome-platform list too, since it seems reasonable for Google folks (probably ChromeOS folks are most active here?) to maintain Google/Chrome drivers.
Let me know if y'all would like this official, and I'll push out a MAINTAINERS patch.
I think that would be a good idea.
Guenter
drivers/firmware/google/coreboot_table.c | 37 +++++++++++++++++++----- 1 file changed, 29 insertions(+), 8 deletions(-)
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c index c52bcaa9def6..9ca21feb9d45 100644 --- a/drivers/firmware/google/coreboot_table.c +++ b/drivers/firmware/google/coreboot_table.c @@ -149,12 +149,8 @@ static int coreboot_table_probe(struct platform_device *pdev) if (!ptr) return -ENOMEM;
- ret = bus_register(&coreboot_bus_type);
- if (!ret) {
ret = coreboot_table_populate(dev, ptr);
if (ret)
bus_unregister(&coreboot_bus_type);
- }
- ret = coreboot_table_populate(dev, ptr);
- memunmap(ptr);
return ret; @@ -169,7 +165,6 @@ static int __cb_dev_unregister(struct device *dev, void *dummy) static int coreboot_table_remove(struct platform_device *pdev) { bus_for_each_dev(&coreboot_bus_type, NULL, NULL, __cb_dev_unregister);
- bus_unregister(&coreboot_bus_type); return 0; }
@@ -199,6 +194,32 @@ static struct platform_driver coreboot_table_driver = { .of_match_table = of_match_ptr(coreboot_of_match), }, }; -module_platform_driver(coreboot_table_driver);
+static int __init coreboot_table_driver_init(void) +{
- int ret;
- ret = bus_register(&coreboot_bus_type);
- if (ret)
return ret;
- ret = platform_driver_register(&coreboot_table_driver);
- if (ret) {
bus_unregister(&coreboot_bus_type);
return ret;
- }
- return 0;
+}
+static void __exit coreboot_table_driver_exit(void) +{
- platform_driver_unregister(&coreboot_table_driver);
- bus_unregister(&coreboot_bus_type);
+}
+module_init(coreboot_table_driver_init); +module_exit(coreboot_table_driver_exit);
- MODULE_AUTHOR("Google, Inc."); MODULE_LICENSE("GPL");
On Wed, Oct 19, 2022 at 06:20:08PM -0700, Guenter Roeck wrote:
On 10/19/22 18:10, Brian Norris wrote:
Currently, get_maintainers.pl tells me Greg should pick this up. But I CC the chrome-platform list too, since it seems reasonable for Google folks (probably ChromeOS folks are most active here?) to maintain Google/Chrome drivers.
Let me know if y'all would like this official, and I'll push out a MAINTAINERS patch.
I think that would be a good idea.
Done:
[PATCH] MAINTAINERS: Add drivers/firmware/google/ entry https://lore.kernel.org/lkml/20221021172624.1.I119456791d197eb7d159f09e7479d...
Brian
Quoting Brian Norris (2022-10-19 18:10:53) [...]
[ 0.114560] do_initcall_level+0x134/0x160 [ 0.114571] do_initcalls+0x60/0xa0 [ 0.114579] do_basic_setup+0x28/0x34 [ 0.114588] kernel_init_freeable+0xf8/0x150 [ 0.114596] kernel_init+0x2c/0x12c [ 0.114607] ret_from_fork+0x10/0x20 [ 0.114624] Code: 5280002b 1100054a b900092a f9800011 (885ffc01) [ 0.114631] ---[ end trace 0000000000000000 ]---
Fixes: b81e3140e412 ("firmware: coreboot: Make bus registration symmetric") Cc: stable@vger.kernel.org Signed-off-by: Brian Norris briannorris@chromium.org
Reviewed-by: Stephen Boyd swboyd@chromium.org
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c index c52bcaa9def6..9ca21feb9d45 100644 --- a/drivers/firmware/google/coreboot_table.c +++ b/drivers/firmware/google/coreboot_table.c @@ -199,6 +194,32 @@ static struct platform_driver coreboot_table_driver = { .of_match_table = of_match_ptr(coreboot_of_match), }, }; -module_platform_driver(coreboot_table_driver);
+static int __init coreboot_table_driver_init(void) +{
int ret;
ret = bus_register(&coreboot_bus_type);
if (ret)
return ret;
ret = platform_driver_register(&coreboot_table_driver);
if (ret) {
bus_unregister(&coreboot_bus_type);
return ret;
}
return 0;
This could be 'return ret' and two lines could be saved, but that is super nitpick so whatever.
Hello:
This patch was applied to chrome-platform/linux.git (for-kernelci) by Greg Kroah-Hartman gregkh@linuxfoundation.org:
On Wed, 19 Oct 2022 18:10:53 -0700 you wrote:
The coreboot_table driver registers a coreboot bus while probing a "coreboot_table" device representing the coreboot table memory region. Probing this device (i.e., registering the bus) is a dependency for the module_init() functions of any driver for this bus (e.g., memconsole-coreboot.c / memconsole_driver_init()).
With synchronous probe, this dependency works OK, as the link order in the Makefile ensures coreboot_table_driver_init() (and thus, coreboot_table_probe()) completes before a coreboot device driver tries to add itself to the bus.
[...]
Here is the summary with links: - firmware: coreboot: Register bus in module init https://git.kernel.org/chrome-platform/c/65946690ed8d
You are awesome, thank you!
Hello:
This patch was applied to chrome-platform/linux.git (for-next) by Greg Kroah-Hartman gregkh@linuxfoundation.org:
On Wed, 19 Oct 2022 18:10:53 -0700 you wrote:
The coreboot_table driver registers a coreboot bus while probing a "coreboot_table" device representing the coreboot table memory region. Probing this device (i.e., registering the bus) is a dependency for the module_init() functions of any driver for this bus (e.g., memconsole-coreboot.c / memconsole_driver_init()).
With synchronous probe, this dependency works OK, as the link order in the Makefile ensures coreboot_table_driver_init() (and thus, coreboot_table_probe()) completes before a coreboot device driver tries to add itself to the bus.
[...]
Here is the summary with links: - firmware: coreboot: Register bus in module init https://git.kernel.org/chrome-platform/c/65946690ed8d
You are awesome, thank you!
linux-stable-mirror@lists.linaro.org