On 3/27/25 13:24, Philippe Mathieu-Daudé wrote:
On 25/3/25 23:44, Richard Henderson wrote:
If i/o does not cover the entire first page, allocate a portion
of ram as an i/o device, so that the entire first page is i/o.

While memory_region_init_ram_device_ptr is happy to allocate
the RAMBlock, it does not register the ram for migration.
Do this by hand.

Signed-off-by: Richard Henderson <richard.hender...@linaro.org>
---
  hw/avr/atmega.h |  1 +
  hw/avr/atmega.c | 39 ++++++++++++++++++++++++++++++++-------
  2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/hw/avr/atmega.h b/hw/avr/atmega.h
index a99ee15c7e..9ac4678231 100644
--- a/hw/avr/atmega.h
+++ b/hw/avr/atmega.h
@@ -41,6 +41,7 @@ struct AtmegaMcuState {
      MemoryRegion flash;
      MemoryRegion eeprom;
      MemoryRegion sram;
+    MemoryRegion sram_io;
      DeviceState *io;
      AVRMaskState pwr[POWER_MAX];
      AVRUsartState usart[USART_MAX];

@@ -240,11 +239,37 @@ static void atmega_realize(DeviceState *dev, Error **errp)
      qdev_realize(DEVICE(&s->cpu), NULL, &error_abort);
      cpudev = DEVICE(&s->cpu);
-    /* SRAM */
-    memory_region_init_ram(&s->sram, OBJECT(dev), "sram", mc->sram_size,
-                           &error_abort);
-    memory_region_add_subregion(get_system_memory(),
-                                OFFSET_DATA + mc->io_size, &s->sram);
+    /*
+     * SRAM
+     *
+     * Softmmu is not able mix i/o and ram on the same page.
+     * Therefore in all cases, the first page exclusively contains i/o.
+     *
+     * If the MCU's i/o region matches the page size, then we can simply
+     * allocate all ram starting at the second page.  Otherwise, we must
+     * allocate some ram as i/o to complete the first page.
+     */
+    assert(mc->io_size == 0x100 || mc->io_size == 0x200);
+    if (mc->io_size >= TARGET_PAGE_SIZE) {
+        memory_region_init_ram(&s->sram, OBJECT(dev), "sram", mc->sram_size,
+                               &error_abort);
+        memory_region_add_subregion(get_system_memory(),
+                                    OFFSET_DATA + mc->io_size, &s->sram);
+    } else {
+        int sram_io_size = TARGET_PAGE_SIZE - mc->io_size;
+        void *sram_io_mem = g_malloc0(sram_io_size);

Please declare sram_io_mem in AtmegaMcuState, after sram_io.

Why?

+
+        memory_region_init_ram_device_ptr(&s->sram_io, OBJECT(dev), 
"sram-as-io",
+                                          sram_io_size, sram_io_mem);

After this, it's accessible as

    s->sram_io->ram_block->host

It wouldn't be accessed in any other way, surely?


r~

Reply via email to