qemu/include/hw/arm
Markus Armbruster e0561e60f1 hw/arm/virt: Support firmware configuration with -blockdev
The ARM virt machines put firmware in flash memory.  To configure it,
you use -drive if=pflash,unit=0,... and optionally -drive
if=pflash,unit=1,...

Why two -drive?  This permits setting up one part of the flash memory
read-only, and the other part read/write.  It also makes upgrading
firmware on the host easier.  Below the hood, we get two separate
flash devices, because we were too lazy to improve our flash device
models to support sector protection.

The problem at hand is to do the same with -blockdev somehow, as one
more step towards deprecating -drive.

We recently solved this problem for x86 PC machines, in commit
ebc29e1bea.  See the commit message for design rationale.

This commit solves it for ARM virt basically the same way: new machine
properties pflash0, pflash1 forward to the onboard flash devices'
properties.  Requires creating the onboard devices in the
.instance_init() method virt_instance_init().  The existing code to
pick up drives defined with -drive if=pflash is replaced by code to
desugar into the machine properties.

There are a few behavioral differences, though:

* The flash devices are always present (x86: only present if
  configured)

* Flash base addresses and sizes are fixed (x86: sizes depend on
  images, mapped back to back below a fixed address)

* -bios configures contents of first pflash (x86: -bios configures ROM
   contents)

* -bios is rejected when first pflash is also configured with -machine
   pflash0=... (x86: bios is silently ignored then)

* -machine pflash1=... does not require -machine pflash0=... (x86: it
   does).

The actual code is a bit simpler than for x86 mostly due to the first
two differences.

Before the patch, all the action is in create_flash(), called from the
machine's .init() method machvirt_init():

    main()
        machine_run_board_init()
            machvirt_init()
                create_flash()
                    create_one_flash() for flash[0]
                        create
                        configure
                            includes obeying -drive if=pflash,unit=0
                        realize
                        map
                        fall back to -bios
                    create_one_flash() for flash[1]
                        create
                        configure
                            includes obeying -drive if=pflash,unit=1
                        realize
                        map
                    update FDT

To make the machine properties work, we need to move device creation
to its .instance_init() method virt_instance_init().

Another complication is machvirt_init()'s computation of
@firmware_loaded: it predicts what create_flash() will do.  Instead of
predicting what create_flash()'s replacement virt_firmware_init() will
do, I decided to have virt_firmware_init() return what it did.
Requires calling it a bit earlier.

Resulting call tree:

    main()
        current_machine = object_new()
            ...
                virt_instance_init()
                    virt_flash_create()
                        virt_flash_create1() for flash[0]
                            create
                            configure: set defaults
                            become child of machine [NEW]
                            add machine prop pflash0 as alias for drive [NEW]
                        virt_flash_create1() for flash[1]
                            create
                            configure: set defaults
                            become child of machine [NEW]
                            add machine prop pflash1 as alias for drive [NEW]
        for all machine props from the command line: machine_set_property()
            ...
                property_set_alias() for machine props pflash0, pflash1
                    ...
                        set_drive() for cfi.pflash01 prop drive
                            this is how -machine pflash0=... etc set
        machine_run_board_init(current_machine);
            virt_firmware_init()
                pflash_cfi01_legacy_drive()
                    legacy -drive if=pflash,unit=0 and =1 [NEW]
                virt_flash_map()
                    virt_flash_map1() for flash[0]
                        configure: num-blocks
                        realize
                        map
                    virt_flash_map1() for flash[1]
                        configure: num-blocks
                        realize
                        map
                fall back to -bios
            virt_flash_fdt()
                update FDT

You have László to thank for making me explain this in detail.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Message-id: 20190416091348.26075-4-armbru@redhat.com
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2019-05-07 12:55:02 +01:00
..
allwinner-a10.h hw/arm/allwinner-a10: Add the 'A' SRAM and the SRAM controller 2019-01-07 15:23:47 +00:00
arm.h hw/arm/armv7m: Remove unused armv7m_init() function 2018-06-15 15:23:34 +01:00
armsse.h hw/arm/armsse: Wire up the MHUs 2019-02-28 11:03:04 +00:00
armv7m.h armv7m: Pass through start-powered-off CPU property 2019-02-01 14:55:41 +00:00
aspeed_soc.h hw/arm/aspeed: simplify using the 'unimplemented device' for aspeed_soc.io 2018-02-15 18:29:36 +00:00
aspeed.h hw/arm/aspeed: Add an Aspeed machine class 2018-09-25 15:13:24 +01:00
bcm2835_peripherals.h hw: Do not include "exec/address-spaces.h" if it is not necessary 2018-06-01 14:15:10 +02:00
bcm2836.h hw/arm/bcm2836: Create proper bcm2837 device 2018-03-19 18:23:24 +00:00
digic.h qemu-common: push cpu.h inclusion out of qemu-common.h 2016-05-19 16:42:29 +02:00
exynos4210.h hw/arm/exynos: Move DRAM initialization next boards 2017-06-13 14:56:57 +01:00
fdt.h hw/arm/sysbus-fdt: enable vfio-calxeda-xgmac dynamic instantiation 2015-06-19 14:17:44 +01:00
fsl-imx6.h fsl-imx6: Swap Ethernet interrupt defines 2018-03-19 18:23:24 +00:00
fsl-imx6ul.h i.MX6UL: Add i.MX6UL SOC 2018-08-16 14:05:28 +01:00
fsl-imx7.h i.MX: Add i.MX7 SOC implementation. 2018-03-09 17:09:43 +00:00
fsl-imx25.h imx_fec: Reserve full FSL_IMX25_FEC_SIZE page for the register file 2018-01-11 13:25:38 +00:00
fsl-imx31.h i.MX: Split the CCM class into an abstract base class and a concrete class 2015-12-17 13:37:15 +00:00
linux-boot-if.h qom: make interface types abstract 2018-12-11 15:45:22 -02:00
msf2-soc.h msf2: Add Smartfusion2 SoC 2017-09-21 16:36:56 +01:00
nrf51_soc.h arm: Instantiate NRF51 special NVM's and NVMC 2019-02-01 15:32:17 +00:00
nrf51.h arm: Stub out NRF51 TWI magnetometer/accelerometer detection 2019-01-29 11:46:03 +00:00
omap.h hw/devices: Move TI touchscreen declarations into a new header 2019-04-29 17:57:21 +01:00
primecell.h hw: move headers to include/ 2013-04-08 18:13:10 +02:00
pxa.h hw/pcmcia: Remove PCMCIACardState from "qemu/typedefs.h" 2019-01-22 05:14:32 +01:00
raspi_platform.h bcm2835_peripherals: add rollup device for bcm2835 peripherals 2016-02-03 15:00:45 +00:00
sharpsl.h Replace all occurances of __FUNCTION__ with __func__ 2018-01-22 09:46:18 +01:00
smmu-common.h hw/arm/smmuv3: Remove SMMUNotifierNode 2019-04-29 17:35:57 +01:00
smmuv3.h hw/arm/smmuv3: Cache/invalidate config data 2018-06-26 17:50:42 +01:00
soc_dma.h Clean up decorations and whitespace around header guards 2016-07-12 16:20:46 +02:00
stm32f205_soc.h arm: drop intermediate cpu_model -> cpu type parsing and use cpu type directly 2017-09-19 09:09:32 -03:00
sysbus-fdt.h arm/boot: split load_dtb() from arm_load_kernel() 2018-05-10 18:10:56 +01:00
virt.h hw/arm/virt: Support firmware configuration with -blockdev 2019-05-07 12:55:02 +01:00
xlnx-versal.h hw/arm: versal: Correct the nr of IRQs to 192 2018-12-13 13:48:04 +00:00
xlnx-zynqmp.h arm/xlnx-zynqmp: put APUs and RPUs in separate CPU clusters 2019-01-07 15:23:46 +00:00