Eric Auger <eric.au...@linaro.org> writes: > Device tree nodes for the platform bus and its children dynamic sysbus > devices are added in a machine init done notifier. To load the dtb once, > after those latter nodes are built and before ROM freeze, the actual > arm_load_kernel existing code is moved into a notifier notify function, > arm_load_kernel_notify. arm_load_kernel now only registers the > corresponding notifier. > > Machine files that do not support platform bus stay unchanged. Machine > files willing to support dynamic sysbus devices must call arm_load_kernel > before sysbus-fdt arm_register_platform_bus_fdt_creator to make sure > dynamic sysbus device nodes are integrated in the dtb. > > Signed-off-by: Eric Auger <eric.au...@linaro.org> > Reviewed-by: Shannon Zhao <zhaoshengl...@huawei.com> > Reviewed-by: Alexander Graf <ag...@suse.de>
Reviewed-by: Alex Bennée <alex.ben...@linaro.org> > > --- > > v8 -> v9: > - fix compilation with arm-linux-user > - reorder fields in ArmLoadKernelNotifier and use DO_UPCAST > > v7 -> v8: > - Add Reviewed-by from Alex & Shannon > - rebase on 2.2.0 > > v6: creation of this patch file > --- > hw/arm/boot.c | 14 +++++++++++++- > include/hw/arm/arm.h | 28 ++++++++++++++++++++++++++++ > 2 files changed, 41 insertions(+), 1 deletion(-) > > diff --git a/hw/arm/boot.c b/hw/arm/boot.c > index a48d1b2..5ac5479 100644 > --- a/hw/arm/boot.c > +++ b/hw/arm/boot.c > @@ -555,7 +555,7 @@ static void load_image_to_fw_cfg(FWCfgState *fw_cfg, > uint16_t size_key, > fw_cfg_add_bytes(fw_cfg, data_key, data, size); > } > > -void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) > +static void arm_load_kernel_notify(Notifier *notifier, void *data) > { > CPUState *cs; > int kernel_size; > @@ -566,6 +566,11 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info > *info) > hwaddr entry, kernel_load_offset; > int big_endian; > static const ARMInsnFixup *primary_loader; > + ArmLoadKernelNotifier *n = DO_UPCAST(ArmLoadKernelNotifier, > + notifier, notifier); > + ARMCPU *cpu = n->cpu; > + struct arm_boot_info *info = > + container_of(n, struct arm_boot_info, load_kernel_notifier); > > /* CPU objects (unlike devices) are not automatically reset on system > * reset, so we must always register a handler to do so. If we're > @@ -773,3 +778,10 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info > *info) > ARM_CPU(cs)->env.boot_info = info; > } > } > + > +void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) > +{ > + info->load_kernel_notifier.cpu = cpu; > + info->load_kernel_notifier.notifier.notify = arm_load_kernel_notify; > + > qemu_add_machine_init_done_notifier(&info->load_kernel_notifier.notifier); > +} > diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h > index 5c940eb..760804c 100644 > --- a/include/hw/arm/arm.h > +++ b/include/hw/arm/arm.h > @@ -13,11 +13,21 @@ > > #include "exec/memory.h" > #include "hw/irq.h" > +#include "qemu/notify.h" > > /* armv7m.c */ > qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, > const char *kernel_filename, const char *cpu_model); > > +/* > + * struct used as a parameter of the arm_load_kernel machine init > + * done notifier > + */ > +typedef struct { > + Notifier notifier; /* actual notifier */ > + ARMCPU *cpu; /* handle to the first cpu object */ > +} ArmLoadKernelNotifier; > + > /* arm_boot.c */ > struct arm_boot_info { > uint64_t ram_size; > @@ -64,6 +74,8 @@ struct arm_boot_info { > * the user it should implement this hook. > */ > void (*modify_dtb)(const struct arm_boot_info *info, void *fdt); > + /* machine init done notifier executing arm_load_dtb */ > + ArmLoadKernelNotifier load_kernel_notifier; > /* Used internally by arm_boot.c */ > int is_linux; > hwaddr initrd_start; > @@ -75,6 +87,22 @@ struct arm_boot_info { > */ > bool firmware_loaded; > }; > + > +/** > + * arm_load_kernel - Loads memory with everything needed to boot > + * > + * @cpu: handle to the first CPU object > + * @info: handle to the boot info struct > + * Registers a machine init done notifier that copies to memory > + * everything needed to boot, depending on machine and user options: > + * kernel image, boot loaders, initrd, dtb. Also registers the CPU > + * reset handler. > + * > + * In case the machine file supports the platform bus device and its > + * dynamically instantiable sysbus devices, this function must be called > + * before sysbus-fdt arm_register_platform_bus_fdt_creator. Indeed the > + * machine init done notifiers are called in registration reverse order. > + */ > void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info); > > /* Multiplication factor to convert from system clock ticks to qemu timer -- Alex Bennée