[Skiboot] [PATCH 02/10] Introduce hwprobe facility to avoid hard-coding probe functions
Dan Horák
dan at danny.cz
Tue Jun 29 01:11:37 AEST 2021
On Sat, 26 Jun 2021 12:38:16 +1000
Nicholas Piggin <npiggin at gmail.com> wrote:
> From: Stewart Smith <stewart at flamingspork.com>
>
> hwprobe is a little system to have different hardware probing modules
> run in the dependency order they choose rather than hard coding
> that order in core/init.c.
I already commented in January, but the special linker section plus
start/end label style is not compatible with LTO and possibly relies on
undefined behaviour in the C language. I don't think LTO is hot topic
for system firmware, but it could change. So at minimum it should be
documented in the commit message.
https://lists.ozlabs.org/pipermail/skiboot/2021-January/017470.html
https://bugzilla.redhat.com/show_bug.cgi?id=1877485#c14
https://sigrok.org/bugzilla/show_bug.cgi?id=1433
Dan
>
> Signed-off-by: Stewart Smith <stewart at flamingspork.com>
> ---
> core/Makefile.inc | 1 +
> core/hwprobe.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++
> core/init.c | 3 ++
> include/skiboot.h | 39 +++++++++++++++++++++++++-
> skiboot.lds.S | 6 ++++
> 5 files changed, 118 insertions(+), 1 deletion(-)
> create mode 100644 core/hwprobe.c
>
> diff --git a/core/Makefile.inc b/core/Makefile.inc
> index 829800e5b..f80019b6a 100644
> --- a/core/Makefile.inc
> +++ b/core/Makefile.inc
> @@ -13,6 +13,7 @@ CORE_OBJS += timer.o i2c.o rtc.o flash.o sensor.o ipmi-opal.o
> CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o powercap.o psr.o
> CORE_OBJS += pci-dt-slot.o direct-controls.o cpufeatures.o
> CORE_OBJS += flash-firmware-versions.o opal-dump.o
> +CORE_OBJS += hwprobe.o
>
> ifeq ($(SKIBOOT_GCOV),1)
> CORE_OBJS += gcov-profiling.o
> diff --git a/core/hwprobe.c b/core/hwprobe.c
> new file mode 100644
> index 000000000..de331af48
> --- /dev/null
> +++ b/core/hwprobe.c
> @@ -0,0 +1,70 @@
> +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
> +/* Copyright 2021 Stewart Smith */
> +
> +#define pr_fmt(fmt) "HWPROBE: " fmt
> +#include <skiboot.h>
> +#include <string.h>
> +
> +static bool hwprobe_deps_satisfied(const struct hwprobe *hwp)
> +{
> + struct hwprobe *hwprobe;
> + const char *dep;
> + unsigned int i;
> +
> + if (hwp->deps == NULL)
> + return true;
> +
> + dep = hwp->deps[0];
> +
> + prlog(PR_TRACE, "Checking deps for %s\n", hwp->name);
> +
> + while (dep != NULL) {
> + prlog(PR_TRACE, "Checking %s dep %s\n", hwp->name, dep);
> + hwprobe = &__hwprobes_start;
> + for (i = 0; &hwprobe[i] < &__hwprobes_end; i++) {
> + if(strcmp(hwprobe[i].name,dep) == 0 &&
> + !hwprobe[i].probed)
> + return false;
> + }
> + dep++;
> + }
> +
> + prlog(PR_TRACE, "deps for %s are satisfied!\n", hwp->name);
> + return true;
> +
> +}
> +
> +void probe_hardware(void)
> +{
> + struct hwprobe *hwprobe;
> + unsigned int i;
> + bool work_todo = true;
> + bool did_something = true;
> +
> + while (work_todo) {
> + work_todo = false;
> + did_something = false;
> + hwprobe = &__hwprobes_start;
> + prlog(PR_DEBUG, "Begin loop\n");
> + for (i = 0; &hwprobe[i] < &__hwprobes_end; i++) {
> + if (hwprobe[i].probed)
> + continue;
> + if (hwprobe_deps_satisfied(&hwprobe[i])) {
> + prlog(PR_DEBUG, "Probing %s...\n", hwprobe[i].name);
> + if (hwprobe[i].probe)
> + hwprobe[i].probe();
> + did_something = true;
> + hwprobe[i].probed = true;
> + } else {
> + prlog(PR_DEBUG, "Dependencies for %s not yet satisfied, skipping\n",
> + hwprobe[i].name);
> + work_todo = true;
> + }
> + }
> +
> + if (work_todo && !did_something) {
> + prlog(PR_ERR, "Cannot satisfy dependencies! Bailing out\n");
> + break;
> + }
> + }
> +}
> diff --git a/core/init.c b/core/init.c
> index d5ba67edd..ed3229172 100644
> --- a/core/init.c
> +++ b/core/init.c
> @@ -1333,6 +1333,9 @@ void __noreturn __nomcount main_cpu_entry(const void *fdt)
> probe_npu2();
> probe_npu3();
>
> + /* Probe all HWPROBE hardware we have code linked for*/
> + probe_hardware();
> +
> /* Initialize PCI */
> pci_init_slots();
>
> diff --git a/include/skiboot.h b/include/skiboot.h
> index 331aa9501..d104c7a89 100644
> --- a/include/skiboot.h
> +++ b/include/skiboot.h
> @@ -1,5 +1,7 @@
> // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
> -/* Copyright 2013-2019 IBM Corp. */
> +/* Copyright 2013-2019 IBM Corp.
> + * Copyright 2021 Stewart Smith
> + */
>
> #ifndef __SKIBOOT_H
> #define __SKIBOOT_H
> @@ -342,4 +344,39 @@ extern int fake_nvram_info(uint32_t *total_size);
> extern int fake_nvram_start_read(void *dst, uint32_t src, uint32_t len);
> extern int fake_nvram_write(uint32_t offset, void *src, uint32_t size);
>
> +/*
> + * A bunch of hardware needs to be probed, sometimes in a particular order.
> + * Very simple dependency graph, with a even simpler way to resolve it.
> + * But it means we can now at link time choose what hardware we support.
> + * This struct should not be defined directly but with the macros.
> + */
> +struct hwprobe {
> + const char *name;
> + void (*probe)(void);
> +
> + bool probed;
> +
> + /* NULL or NULL-terminated array of strings */
> + const char **deps;
> +};
> +
> +#define DEFINE_HWPROBE(__name, __probe) \
> +static const struct hwprobe __used __section(".hwprobes") hwprobe_##__name = { \
> + .name = #__name, \
> + .probe = __probe, \
> + .deps = NULL, \
> +}
> +
> +#define DEFINE_HWPROBE_DEPS(__name, __probe, ...) \
> +static const struct hwprobe __used __section(".hwprobes") hwprobe_##__name = { \
> + .name = #__name, \
> + .probe = __probe, \
> + .deps = (const char *[]){ __VA_ARGS__, NULL}, \
> +}
> +
> +extern struct hwprobe __hwprobes_start;
> +extern struct hwprobe __hwprobes_end;
> +
> +extern void probe_hardware(void);
> +
> #endif /* __SKIBOOT_H */
> diff --git a/skiboot.lds.S b/skiboot.lds.S
> index 5a7f9e316..c8e6e747c 100644
> --- a/skiboot.lds.S
> +++ b/skiboot.lds.S
> @@ -164,6 +164,12 @@ SECTIONS
> __platforms_end = .;
> }
>
> + .hwprobes : {
> + __hwprobes_start = .;
> + KEEP(*(.hwprobes))
> + __hwprobes_end = .;
> + }
> +
> /* Relocations */
> . = ALIGN(0x10);
> .dynamic : {
> --
> 2.23.0
>
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
More information about the Skiboot
mailing list