Hi Cédric
> Subject: Re: [PATCH v1 3/3] hw/arm/aspeed_ast27x0: Fix RAM size detection
> failure on BE hosts
>
> On 5/20/25 09:35, Jamin Lin wrote:
> > On big-endian hosts, the aspeed_ram_capacity_write() function
> > previously passed the address of a 64-bit "data" variable directly to
> > address_space_write(), assuming host and guest endianness matched.
> >
> > However, the data is expected to be written in little-endian format to DRAM.
> > On big-endian hosts, this led to incorrect data being written into
> > DRAM, which caused the guest firmware to misdetect the DRAM size.
> >
> > As a result, U-Boot fails to boot and hangs.
> >
> > - Explicitly converting the 32-bit portion of "data" to little-endian format
> > using cpu_to_le32(), storing it in a temporary "uint32_t le_data".
> > - Updating the MemoryRegionOps to restrict access to exactly 4 bytes
> > using .valid.{min,max}_access_size = 4 and .impl.min_access_size = 4.
> >
> > Signed-off-by: Jamin Lin <jamin_...@aspeedtech.com>
> > Fixes: 7436db1 ("aspeed/soc: fix incorrect dram size for AST2700")
> > ---
> > hw/arm/aspeed_ast27x0.c | 21 ++++++++++++++++-----
> > 1 file changed, 16 insertions(+), 5 deletions(-)
> >
> > diff --git a/hw/arm/aspeed_ast27x0.c b/hw/arm/aspeed_ast27x0.c index
> > 1974a25766..7ed0919b3f 100644
> > --- a/hw/arm/aspeed_ast27x0.c
> > +++ b/hw/arm/aspeed_ast27x0.c
> > @@ -335,24 +335,34 @@ static void aspeed_ram_capacity_write(void
> *opaque, hwaddr addr, uint64_t data,
> > AspeedSoCState *s = ASPEED_SOC(opaque);
> > ram_addr_t ram_size;
> > MemTxResult result;
> > + uint32_t le_data;
> >
> > ram_size = object_property_get_uint(OBJECT(&s->sdmc), "ram-size",
> > &error_abort);
> >
> > assert(ram_size > 0);
> >
> > + if (size != 4) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "%s: Unsupported write size: %d (only 4-byte
> allowed)\n",
> > + __func__, size);
> > + return;
> > + }
>
> The core memory subsystem should find such issues if the valid attributes of
> MemoryRegionOps are set correctly.
>
> > + le_data = cpu_to_le32((uint32_t)data);
> > +
> > /*
> > * Emulate ddr capacity hardware behavior.
> > * If writes the data to the address which is beyond the ram size,
> > * it would write the data to the "address % ram_size".
> > */
> > result = address_space_write(&s->dram_as, addr % ram_size,
> > - MEMTXATTRS_UNSPECIFIED, &data,
> 4);
> > + MEMTXATTRS_UNSPECIFIED,
> &le_data,
> > + 4);
>
>
> This should be enough :
>
> address_space_stl_le(&s->dram_as, addr % ram_size, data,
> MEMTXATTRS_UNSPECIFIED, &result);
>
> Sorry for not spotting this earlier. Finding a BE host is difficult.
> Thanks for the time you spent on fixing this issue.
>
Thanks for the review and suggestion.
Will update it.
Jamin
> C.
>
>
> > if (result != MEMTX_OK) {
> > qemu_log_mask(LOG_GUEST_ERROR,
> > "%s: DRAM write failed, addr:0x%"
> HWADDR_PRIx
> > - ", data :0x%" PRIx64 "\n",
> > - __func__, addr % ram_size, data);
> > + ", data :0x%x\n",
> > + __func__, addr % ram_size, le_data);
> > }
> > }
> >
> > @@ -360,9 +370,10 @@ static const MemoryRegionOps
> aspeed_ram_capacity_ops = {
> > .read = aspeed_ram_capacity_read,
> > .write = aspeed_ram_capacity_write,
> > .endianness = DEVICE_LITTLE_ENDIAN,
> > + .impl.min_access_size = 4,
> > .valid = {
> > - .min_access_size = 1,
> > - .max_access_size = 8,
> > + .min_access_size = 4,
> > + .max_access_size = 4,
> > },
> > };
> >