qemu/include
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
..
authz filemon: fix watch IDs to avoid potential wraparound issues 2019-04-02 13:52:02 +01:00
block block: introduce byte-based io helpers 2019-04-30 15:29:00 +02:00
chardev char: move SpiceChardev and open_spice_port() to spice.h header 2019-02-21 14:09:17 +01:00
crypto Don't talk about the LGPL if the file is licensed under the GPL 2019-01-30 10:51:20 +01:00
disas include: Move fprintf_function to disas/ 2019-04-18 22:18:59 +02:00
exec Add tcg_gen_extract2_*. 2019-04-28 11:43:10 +01:00
fpu softfloat: Implement float128_to_uint32 2019-02-26 14:05:19 +00:00
hw hw/arm/virt: Support firmware configuration with -blockdev 2019-05-07 12:55:02 +01:00
io io: Make qio_channel_yield() interruptible 2019-02-25 15:03:19 +01:00
libdecnumber Clean up ill-advised or unusual header guards 2016-07-12 16:20:46 +02:00
migration slirp: use libslirp migration code 2019-03-07 12:46:31 +01:00
monitor monitor: Clean up how monitor_disas() funnels output to monitor 2019-04-18 22:18:59 +02:00
net net: Add a network device specific self-announcement ability 2019-03-05 11:27:41 +08:00
qapi qapi: remove qmp_unregister_command() 2019-02-18 14:44:05 +01:00
qemu hw/devices: Move TI touchscreen declarations into a new header 2019-04-29 17:57:21 +01:00
qom cpu: Rename parse_cpu_model() to parse_cpu_option() 2019-04-25 14:17:35 -03:00
scsi avoid TABs in files that only contain a few 2019-01-11 15:46:56 +01:00
standard-headers * cpu-exec fixes (Emilio, Laurent) 2019-02-05 19:39:22 +00:00
sysemu accel: Remove unused AccelClass::available field 2019-05-02 16:56:33 +02:00
ui spice: set device address and device display ID in QXL interface 2019-02-21 10:15:26 +01:00
elf.h elf: Add RISC-V PSABI ELF header defines 2019-03-19 05:14:39 -07:00
glib-compat.h slirp: Move g_spawn_async_with_fds_qemu compatibility to slirp/ 2019-02-07 15:49:08 +02:00
qemu-common.h include: Include fprintf-fn.h only where needed 2019-04-18 22:18:59 +02:00
qemu-io.h qemu-io: Let command functions return error code 2018-06-11 16:18:45 +02:00
trace-tcg.h trace: get rid of generated-events.h/generated-events.c 2016-10-12 09:54:52 +02:00