diff mbox series

[v2,07/16] hw/char/xilinx_uartlite: Make device endianness configurable

Message ID 20241107012223.94337-8-philmd@linaro.org
State New
Headers show
Series hw/microblaze: Allow running cross-endian vCPUs | expand

Commit Message

Philippe Mathieu-Daudé Nov. 7, 2024, 1:22 a.m. UTC
Replace the DEVICE_NATIVE_ENDIAN MemoryRegionOps by a pair
of DEVICE_LITTLE_ENDIAN / DEVICE_BIG_ENDIAN.
Add the "little-endian" property to select the device
endianness, defaulting to little endian.
Set the proper endianness on the single machine using the
device.

Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
 hw/char/xilinx_uartlite.c                | 44 ++++++++++++++++--------
 hw/microblaze/petalogix_s3adsp1800_mmu.c |  1 +
 2 files changed, 31 insertions(+), 14 deletions(-)

Comments

Richard Henderson Nov. 7, 2024, 10:27 a.m. UTC | #1
On 11/7/24 01:22, Philippe Mathieu-Daudé wrote:
> Replace the DEVICE_NATIVE_ENDIAN MemoryRegionOps by a pair
> of DEVICE_LITTLE_ENDIAN / DEVICE_BIG_ENDIAN.
> Add the "little-endian" property to select the device
> endianness, defaulting to little endian.
> Set the proper endianness on the single machine using the
> device.
> 
> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
> ---
>   hw/char/xilinx_uartlite.c                | 44 ++++++++++++++++--------
>   hw/microblaze/petalogix_s3adsp1800_mmu.c |  1 +
>   2 files changed, 31 insertions(+), 14 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

> +static const MemoryRegionOps uart_ops[2] = {
> +    {
> +        .read = uart_read,
> +        .write = uart_write,
> +        .endianness = DEVICE_BIG_ENDIAN,
> +        .impl = {
> +            .min_access_size = 4,
> +            .max_access_size = 4,
> +        },
> +        .valid = {
> +            .min_access_size = 1,
> +            .max_access_size = 4,
> +        },
> +    }, {
> +        .read = uart_read,
> +        .write = uart_write,
> +        .endianness = DEVICE_LITTLE_ENDIAN,
> +        .impl = {
> +            .min_access_size = 4,
> +            .max_access_size = 4,
> +        },
> +        .valid = {
> +            .min_access_size = 1,
> +            .max_access_size = 4,
> +        },
>       }
>   };

Having looked at several of these now, it occurs to me that you can avoid repetition:

static const MemoryRegionOps uart_ops[2] = {
     [0 ... 1] = {
         .read = uart_read,
         etc,
     },
     [0].endianness = DEVICE_BIG_ENDIAN,
     [1].endianness = DEVICE_LITTLE_ENDIAN,
};


r~
Philippe Mathieu-Daudé Nov. 8, 2024, 3:06 p.m. UTC | #2
On 7/11/24 10:27, Richard Henderson wrote:
> On 11/7/24 01:22, Philippe Mathieu-Daudé wrote:
>> Replace the DEVICE_NATIVE_ENDIAN MemoryRegionOps by a pair
>> of DEVICE_LITTLE_ENDIAN / DEVICE_BIG_ENDIAN.
>> Add the "little-endian" property to select the device
>> endianness, defaulting to little endian.
>> Set the proper endianness on the single machine using the
>> device.
>>
>> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
>> ---
>>   hw/char/xilinx_uartlite.c                | 44 ++++++++++++++++--------
>>   hw/microblaze/petalogix_s3adsp1800_mmu.c |  1 +
>>   2 files changed, 31 insertions(+), 14 deletions(-)
> 
> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
> 
>> +static const MemoryRegionOps uart_ops[2] = {
>> +    {
>> +        .read = uart_read,
>> +        .write = uart_write,
>> +        .endianness = DEVICE_BIG_ENDIAN,
>> +        .impl = {
>> +            .min_access_size = 4,
>> +            .max_access_size = 4,
>> +        },
>> +        .valid = {
>> +            .min_access_size = 1,
>> +            .max_access_size = 4,
>> +        },
>> +    }, {
>> +        .read = uart_read,
>> +        .write = uart_write,
>> +        .endianness = DEVICE_LITTLE_ENDIAN,
>> +        .impl = {
>> +            .min_access_size = 4,
>> +            .max_access_size = 4,
>> +        },
>> +        .valid = {
>> +            .min_access_size = 1,
>> +            .max_access_size = 4,
>> +        },
>>       }
>>   };
> 
> Having looked at several of these now, it occurs to me that you can 
> avoid repetition:
> 
> static const MemoryRegionOps uart_ops[2] = {
>      [0 ... 1] = {
>          .read = uart_read,
>          etc,
>      },
>      [0].endianness = DEVICE_BIG_ENDIAN,
>      [1].endianness = DEVICE_LITTLE_ENDIAN,
> };

Thank you :) I had the idea it was possible then forgot about it.
diff mbox series

Patch

diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c
index 3022b3d8ef..c43bf1a030 100644
--- a/hw/char/xilinx_uartlite.c
+++ b/hw/char/xilinx_uartlite.c
@@ -57,6 +57,7 @@ 
 struct XilinxUARTLite {
     SysBusDevice parent_obj;
 
+    bool little_endian_model;
     MemoryRegion mmio;
     CharBackend chr;
     qemu_irq irq;
@@ -166,21 +167,36 @@  uart_write(void *opaque, hwaddr addr,
     uart_update_irq(s);
 }
 
-static const MemoryRegionOps uart_ops = {
-    .read = uart_read,
-    .write = uart_write,
-    .endianness = DEVICE_NATIVE_ENDIAN,
-    .impl = {
-        .min_access_size = 4,
-        .max_access_size = 4,
-    },
-    .valid = {
-        .min_access_size = 1,
-        .max_access_size = 4
+static const MemoryRegionOps uart_ops[2] = {
+    {
+        .read = uart_read,
+        .write = uart_write,
+        .endianness = DEVICE_BIG_ENDIAN,
+        .impl = {
+            .min_access_size = 4,
+            .max_access_size = 4,
+        },
+        .valid = {
+            .min_access_size = 1,
+            .max_access_size = 4,
+        },
+    }, {
+        .read = uart_read,
+        .write = uart_write,
+        .endianness = DEVICE_LITTLE_ENDIAN,
+        .impl = {
+            .min_access_size = 4,
+            .max_access_size = 4,
+        },
+        .valid = {
+            .min_access_size = 1,
+            .max_access_size = 4,
+        },
     }
 };
 
 static Property xilinx_uartlite_properties[] = {
+    DEFINE_PROP_BOOL("little-endian", XilinxUARTLite, little_endian_model, true),
     DEFINE_PROP_CHR("chardev", XilinxUARTLite, chr),
     DEFINE_PROP_END_OF_LIST(),
 };
@@ -219,6 +235,9 @@  static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
 {
     XilinxUARTLite *s = XILINX_UARTLITE(dev);
 
+    memory_region_init_io(&s->mmio, OBJECT(dev),
+                          &uart_ops[s->little_endian_model],
+                          s, "xlnx.xps-uartlite", R_MAX * 4);
     qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
                              uart_event, NULL, s, NULL, true);
 }
@@ -228,9 +247,6 @@  static void xilinx_uartlite_init(Object *obj)
     XilinxUARTLite *s = XILINX_UARTLITE(obj);
 
     sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
-
-    memory_region_init_io(&s->mmio, obj, &uart_ops, s,
-                          "xlnx.xps-uartlite", R_MAX * 4);
     sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
 }
 
diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c
index c0136d84c3..bd8b85fa54 100644
--- a/hw/microblaze/petalogix_s3adsp1800_mmu.c
+++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c
@@ -107,6 +107,7 @@  petalogix_s3adsp1800_init(MachineState *machine)
     }
 
     dev = qdev_new(TYPE_XILINX_UARTLITE);
+    qdev_prop_set_bit(dev, "little-endian", !TARGET_BIG_ENDIAN);
     qdev_prop_set_chr(dev, "chardev", serial_hd(0));
     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, UARTLITE_BASEADDR);