[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [Qemu-ppc] [PATCH v2 06/11] sam460ex: Don't size flash

From: BALATON Zoltan
Subject: Re: [Qemu-devel] [Qemu-ppc] [PATCH v2 06/11] sam460ex: Don't size flash memory to match backing image
Date: Tue, 5 Mar 2019 23:49:56 +0100 (CET)
User-agent: Alpine 2.21.9999 (BSF 287 2018-06-16)


On Tue, 5 Mar 2019, Philippe Mathieu-Daudé wrote:
On 2/26/19 8:34 PM, Markus Armbruster wrote:
Machine "sam460ex" maps its flash memory at address 0xFFF00000.  When
no image is supplied, its size is 1MiB (0x100000), and 512KiB of ROM
get mapped on top of its second half.  Else, it's the size of the
image rounded up to the next multiple of 64KiB.

The rounding is actually useless: pflash_cfi01_realize() fails with
"failed to read the initial flash content" unless it's a no-op.

I have no idea what happens when the pflash's size exceeds 1MiB.
Useful outcomes seem unlikely.

With PFlashCFI02, it depends of the @nb_mappings parameter, which tries
to emulates how the bus connects the pflash (which address lines are

PFlashCFI01 doesn't support the feature to remap its content in aliases
(which might look unfortunate, because boards end doing it, in different

I think this is all theoretical at the moment since we don't actually model the flash functions of this board (at least I haven't tested that at all) and unless it somehow uses it in ways I'm unaware of I think currently only the ROM is used.

For this device we have:

 (qemu) info mtree
 0000000000000000-ffffffffffffffff (prio 0, i/o): system
 00000004fff00000-00000004ffffffff (prio 0, romd): sam460ex.flash

I'm not familiar with this arch/machine, let's assume the system bus is
32bit, and the flash has a 8bit word (we have 8 data lines connected to
the pflash).

Maybe this can help:

Unfortunately I don't have any more detailed docs where it's explained more but according to the above and in my limited understanding the SoC could handle larger flash chips but this board has 512 MB. We have not changed it now because I'm not sure if it would break anything and I don't have time to test it so Marcus just added a comment to remind about this and we're happy with that for now and could come back to it separately.

The 'no image' is 1MiB.

1 MiB = 8 Mbit
8 Mbit / 32 = 2 ^ 18
We need 18 address lines to reach the whole flash.

What happens if we connect a 2MiB flash? We need 19 addr lines.

If we only have 18 lines to connect our flash, we can hardwire our last
line as 0 or 1.

- line #17 hardwired as 0:
Only the bottom part of the flash is accessible (range 0x000000..0x0fffff).
CPU reading 0x4fff00000 read flash offset 0x0.
Using CFI it is still a announced as 2MiB.

- line #17 hardwired as 1:
Only the top part of the flash is accessible (range 0x100000..0x1fffff).
Can we trigger any operation from the internal state machine (writing to
address 0x555, named @unlock_addr0 in QEMU) since all access are
hardwardwired on top of 1MiB...?
Yes we can, because the pflash only uses 11 bits for it's I/O, so all
writes are masked and hit the I/O internal unit.
CPU reading 0x4fff00000 read flash offset 0x100000

If we do have 19 lines dedicated to our chip and connect a 512KiB flash,
we 'll use 17 lines and let 2 lines unused.
Regardless the values on the lines #17 and #18, the flash will answer to
the value on lines #0..#16. This might be called MMIO aliasing, and is
what setup the @nb_mappings argument.
This example with nb_mappings=4 would mean:
"I have a 2MiB I/O space and a 512KiB flash, map it and create 3 aliases".

Back to the architecture, what matters here is that the CPU reset vector
is always user-controlled (mapped on a flash device).
This arch has reset_vector @0x4fffffffc.
You could also map a 256KiB pflash at 0x4fffc0000, as long as the reset
vector is covered. If you map it at 0x4fff00000 or 0x4fff80000 it won't!

This explanation is not arch-specific (adapting the reset vector to each

I guess memory at the end of the address space remains unmapped when
it's smaller than 1MiB.  Again, useful outcomes seem unlikely.

If you map a 512KiB flash at 0x4fff00000, then the reset vector is not
covered. At 0x4fff80000 it is.

Yes, I said the same before but this would be a separate patch and would need more testing so it wasn't included in this series. Since it works as it is now this can wait until later when it can be cleaned up. If we want to model the actual board we don't have to consider different flash sizes than the 512 MB that the board has so everything else is probably "overthinking" it.


The physical hardware appears to have 512KiB of flash memory:

For now, just set the flash memory size to 1MiB regardless of image
size, and document the mess.

Cc: BALATON Zoltan <address@hidden>
Signed-off-by: Markus Armbruster <address@hidden>
 hw/ppc/sam460ex.c | 41 ++++++++++++++++++++++++++---------------
 1 file changed, 26 insertions(+), 15 deletions(-)

diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index 75250d49e4..0c919529f8 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -91,32 +91,43 @@ struct boot_info {

 static int sam460ex_load_uboot(void)
+    /*
+     * This first creates 1MiB of flash memory mapped at the end of
+     * the 32-bit address space (0xFFF00000..0xFFFFFFFF).
+     *
+     * If_PFLASH unit 0 is defined, the flash memory is initialized
+     * from that block backend.
+     *
+     * Else, it's initialized to zero.  And then 512KiB of ROM get
+     * mapped on top of its second half (0xFFF80000..0xFFFFFFFF),
+     * initialized from u-boot-sam460-20100605.bin.

I think the correct check is:

   if (! something_mapped_at(0x4fffffffc)) {
               0x500000000 - sizeof("u-boot-sam460.bin"));


   if (!memory_region_present(get_system_memory(), 0x4fffffffc)) {
       /* Current uboot ROM is 512KiB */
       /* TODO check [0x500000000 - 512KiB,0x500000000 - 1] unmapped */
                          UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32),



+     *
+     * This doesn't smell right.
+     *
+     * The physical hardware appears to have 512KiB flash memory.
+     *
+     * TODO Figure out what we really need here, and clean this up.
+     */
     DriveInfo *dinfo;
-    BlockBackend *blk = NULL;
-    hwaddr base = FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32);
-    long bios_size = FLASH_SIZE;
-    int fl_sectors;

     dinfo = drive_get(IF_PFLASH, 0, 0);
-    if (dinfo) {
-        blk = blk_by_legacy_dinfo(dinfo);
-        bios_size = blk_getlength(blk);
-    }
-    fl_sectors = (bios_size + 65535) >> 16;
-    if (!pflash_cfi01_register(base, NULL, "sam460ex.flash", bios_size,
-                               blk, 64 * KiB, fl_sectors,
+    if (!pflash_cfi01_register(FLASH_BASE | ((hwaddr)FLASH_BASE_H << 32),
+                               NULL, "sam460ex.flash", FLASH_SIZE,
+                               dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
+                               64 * KiB, FLASH_SIZE / (64 * KiB),
                                1, 0x89, 0x18, 0x0000, 0x0, 1)) {
         error_report("Error registering flash memory");
         /* XXX: return an error instead? */

-    if (!blk) {
+    if (!dinfo) {
         /*error_report("No flash image given with the 'pflash' parameter,"
                 " using default u-boot image");*/
-        base = UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32);
-        rom_add_file_fixed(UBOOT_FILENAME, base, -1);
+        rom_add_file_fixed(UBOOT_FILENAME,
+                           UBOOT_LOAD_BASE | ((hwaddr)FLASH_BASE_H << 32),
+                           -1);

     return 0;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]