Peter Maydell <peter.mayd...@linaro.org> writes:

> On Thu, 19 Sept 2024 at 14:11, Alex Bennée <alex.ben...@linaro.org> wrote:
>>
>> Peter Maydell <peter.mayd...@linaro.org> writes:
>> > While I'm looking at the code, this caught my eye:
>> >
>> >     case QEMU_PLUGIN_MEM_VALUE_U64:
>> >     {
>> >         uint64_t *p = (uint64_t *) &ri->data[offset];
>> >         uint64_t val = be ? htobe64(value.data.u64) : 
>> > htole64(value.data.u64);
>> >         if (is_store) {
>> >             *p = val;
>> >         } else if (*p != val) {
>> >             unseen_data = true;
>> >         }
>> >         break;
>> >     }
>> >
>> > Casting a random byte pointer to uint64_t* like that
>> > and dereferencing it isn't valid -- it can fault if
>> > it's not aligned correctly.
>>
>> Hmm in the normal case of x86 hosts we will never hit this.
>
> Not necessarily -- some x86 SIMD insns enforce alignment.
>
>> I guess we
>> could do a memcpy step and then the byteswap?
>
> That's what bswap.h does, yes.
>
>> Could it be included directly without bringing in the rest of QEMU's
>> include deps?
>
> It's technically quite close to standalone I think,
> but I think it would be a bad idea to directly include
> it because once you put QEMU's include/ on the plugin
> compile include path then that's a slippery slope to
> the plugins not actually being standalone code any more.

In this case tests/tcg/plugins are built for testing the implementation.
We could let it slide to save on just copy and pasting the whole file:

--8<---------------cut here---------------start------------->8---
modified   tests/tcg/plugins/mem.c
@@ -9,10 +9,23 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <endian.h>
 #include <stdio.h>
 #include <glib.h>
 
+/*
+ * plugins should not include anything from QEMU aside from the
+ * API header. However the bswap.h header is sufficiently self
+ * contained that we include it here to avoid code duplication.
+ */
+#define HOST_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define HOST_LONG_BITS (__SIZEOF_POINTER__ * 8)
+#ifndef glue
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+#define stringify(s) tostring(s)
+#define tostring(s) #s
+#endif
+#include <bswap.h>
 #include <qemu-plugin.h>
 
 QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
@@ -154,33 +167,45 @@ static void update_region_info(uint64_t region, uint64_t 
offset,
     case QEMU_PLUGIN_MEM_VALUE_U16:
     {
         uint16_t *p = (uint16_t *) &ri->data[offset];
-        uint16_t val = be ? htobe16(value.data.u16) : htole16(value.data.u16);
         if (is_store) {
-            *p = val;
-        } else if (*p != val) {
-            unseen_data = true;
+            if (be) {
+                stw_be_p(p, value.data.u16);
+            } else {
+                stw_le_p(p, value.data.u16);
+            }
+        } else {
+            uint16_t val = be ? lduw_be_p(p) : lduw_le_p(p);
+            unseen_data = val != value.data.u16;
         }
         break;
     }
     case QEMU_PLUGIN_MEM_VALUE_U32:
     {
         uint32_t *p = (uint32_t *) &ri->data[offset];
-        uint32_t val = be ? htobe32(value.data.u32) : htole32(value.data.u32);
         if (is_store) {
-            *p = val;
-        } else if (*p != val) {
-            unseen_data = true;
+            if (be) {
+                stl_be_p(p, value.data.u32);
+            } else {
+                stl_le_p(p, value.data.u32);
+            }
+        } else {
+            uint32_t val = be ? ldl_be_p(p) : ldl_le_p(p);
+            unseen_data = val != value.data.u32;
         }
         break;
     }
     case QEMU_PLUGIN_MEM_VALUE_U64:
     {
         uint64_t *p = (uint64_t *) &ri->data[offset];
-        uint64_t val = be ? htobe64(value.data.u64) : htole64(value.data.u64);
         if (is_store) {
-            *p = val;
-        } else if (*p != val) {
-            unseen_data = true;
+            if (be) {
+                stq_be_p(p, value.data.u64);
+            } else {
+                stq_le_p(p, value.data.u64);
+            }
+        } else {
+            uint64_t val = be ? ldq_be_p(p) : ldq_le_p(p);
+            unseen_data = val != value.data.u64;
         }
         break;
--8<---------------cut here---------------end--------------->8---

-- 
Alex Bennée
Virtualisation Tech Lead @ Linaro

Reply via email to