diff mbox

[v8,04/11] public: xen.h: add definitions for UUID handling

Message ID 1507650771-16631-5-git-send-email-volodymyr_babchuk@epam.com (mailing list archive)
State New, archived
Headers show

Commit Message

Volodymyr Babchuk Oct. 10, 2017, 3:52 p.m. UTC
Added type xen_uuid_t. This type represents UUID as an array of 16
bytes in big endian format.

Added macro XEN_DEFINE_UUID that constructs UUID in the usual way:

 XEN_DEFINE_UUID(0x00112233, 0x4455, 0x6677, 0x8899,
		0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff)

will construct UUID 00112233-4455-6677-8899-aabbccddeeff presented as
 {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
  0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}

NB: We define a new structure here rather than re-using EFI_GUID.
EFI_GUID uses a Microsoft-style encoding which, among other things,
mixes little-endian and big-endian. The structure defined in this
patch, unlike EFI_GUID, is compatible with the Linux kernel and libuuid.

Signed-off-by: Volodymyr Babchuk <volodymyr_babchuk@epam.com>
---

 * Changed commit message ("NB:" part). Thanks to George Dunlap
   for suggestion.

---
xen/include/public/xen.h | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

Comments

Jan Beulich Oct. 10, 2017, 4:12 p.m. UTC | #1
>>> On 10.10.17 at 17:52, <volodymyr_babchuk@epam.com> wrote:
> --- a/xen/include/public/xen.h
> +++ b/xen/include/public/xen.h
> @@ -930,6 +930,39 @@ __DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
>  __DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
>  __DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
>  
> +typedef struct
> +{

Please put the opening brace on the previous line.

> +    uint8_t a[16];
> +} xen_uuid_t;
> +
> +/*
> + * XEN_DEFINE_UUID(0x00112233, 0x4455, 0x6677, 0x8899,
> + *                 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff)
> + * will construct UUID 00112233-4455-6677-8899-aabbccddeeff presented as
> + * {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
> + * 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
> + *
> + * NB: This is compatible with Linux kernel and with libuuid, but it is not
> + * compatible with Microsoft, as they use mixed-endian encoding (some
> + * components are little-endian, some are big-endian).
> + */
> +#define XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6)            \
> +    {{((a) >> 24) & 0xFF, ((a) >> 16) & 0xFF,                           \
> +      ((a) >>  8) & 0xFF, ((a) >>  0) & 0xFF,                           \
> +      ((b) >>  8) & 0xFF, ((b) >>  0) & 0xFF,                           \
> +      ((c) >>  8) & 0xFF, ((c) >>  0) & 0xFF,                           \
> +      ((d) >>  8) & 0xFF, ((d) >>  0) & 0xFF,                           \
> +                e1, e2, e3, e4, e5, e6}}
> +
> +/* Compound literals are supported in C99 and later. */
> +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L

I didn't notice this earlier - why no check for __GNUC__?

> +#define XEN_DEFINE_UUID(a, b, c, d, e1, e2, e3, e4, e5, e6)             \
> +    (xen_uuid_t)XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6)

This being (generally) usable as expression, I think it needs
parentheses, so e.g. XEN_DEFINE_UUID(...).a[n] becomes
possible (whatever that may be good for).

Jan
Volodymyr Babchuk Oct. 10, 2017, 5:03 p.m. UTC | #2
Hello Jan,

On 10.10.17 19:12, Jan Beulich wrote:
>>>> On 10.10.17 at 17:52, <volodymyr_babchuk@epam.com> wrote:
>> --- a/xen/include/public/xen.h
>> +++ b/xen/include/public/xen.h
>> @@ -930,6 +930,39 @@ __DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
>>   __DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
>>   __DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
>>   
>> +typedef struct
>> +{
> 
> Please put the opening brace on the previous line.
Will fix.

>> +    uint8_t a[16];
>> +} xen_uuid_t;
>> +
>> +/*
>> + * XEN_DEFINE_UUID(0x00112233, 0x4455, 0x6677, 0x8899,
>> + *                 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff)
>> + * will construct UUID 00112233-4455-6677-8899-aabbccddeeff presented as
>> + * {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
>> + * 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
>> + *
>> + * NB: This is compatible with Linux kernel and with libuuid, but it is not
>> + * compatible with Microsoft, as they use mixed-endian encoding (some
>> + * components are little-endian, some are big-endian).
>> + */
>> +#define XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6)            \
>> +    {{((a) >> 24) & 0xFF, ((a) >> 16) & 0xFF,                           \
>> +      ((a) >>  8) & 0xFF, ((a) >>  0) & 0xFF,                           \
>> +      ((b) >>  8) & 0xFF, ((b) >>  0) & 0xFF,                           \
>> +      ((c) >>  8) & 0xFF, ((c) >>  0) & 0xFF,                           \
>> +      ((d) >>  8) & 0xFF, ((d) >>  0) & 0xFF,                           \
>> +                e1, e2, e3, e4, e5, e6}}
>> +
>> +/* Compound literals are supported in C99 and later. */
>> +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
> 
> I didn't notice this earlier - why no check for __GNUC__?
I have seen pattern "#if defined (__STDC_VERSION__) && __STDC_VERSION__ 
 >= 199901" in various places in XEN, so I did it alike.
Also, I'm using C99 feature, not gcc-only one.

>> +#define XEN_DEFINE_UUID(a, b, c, d, e1, e2, e3, e4, e5, e6)             \
>> +    (xen_uuid_t)XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6)
> 
> This being (generally) usable as expression, I think it needs
> parentheses, so e.g. XEN_DEFINE_UUID(...).a[n] becomes
> possible (whatever that may be good for).
Good point, thanks.
Jan Beulich Oct. 11, 2017, 8:07 a.m. UTC | #3
>>> On 10.10.17 at 19:03, <volodymyr_babchuk@epam.com> wrote:
> On 10.10.17 19:12, Jan Beulich wrote:
>>>>> On 10.10.17 at 17:52, <volodymyr_babchuk@epam.com> wrote:
>>> +    uint8_t a[16];
>>> +} xen_uuid_t;
>>> +
>>> +/*
>>> + * XEN_DEFINE_UUID(0x00112233, 0x4455, 0x6677, 0x8899,
>>> + *                 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff)
>>> + * will construct UUID 00112233-4455-6677-8899-aabbccddeeff presented as
>>> + * {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
>>> + * 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
>>> + *
>>> + * NB: This is compatible with Linux kernel and with libuuid, but it is not
>>> + * compatible with Microsoft, as they use mixed-endian encoding (some
>>> + * components are little-endian, some are big-endian).
>>> + */
>>> +#define XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6)            \
>>> +    {{((a) >> 24) & 0xFF, ((a) >> 16) & 0xFF,                           \
>>> +      ((a) >>  8) & 0xFF, ((a) >>  0) & 0xFF,                           \
>>> +      ((b) >>  8) & 0xFF, ((b) >>  0) & 0xFF,                           \
>>> +      ((c) >>  8) & 0xFF, ((c) >>  0) & 0xFF,                           \
>>> +      ((d) >>  8) & 0xFF, ((d) >>  0) & 0xFF,                           \
>>> +                e1, e2, e3, e4, e5, e6}}
>>> +
>>> +/* Compound literals are supported in C99 and later. */
>>> +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
>> 
>> I didn't notice this earlier - why no check for __GNUC__?
> I have seen pattern "#if defined (__STDC_VERSION__) && __STDC_VERSION__ 

But if you check, all of the existing ones have
"#elif defined(__GNUC__)".

>  >= 199901" in various places in XEN, so I did it alike.
> Also, I'm using C99 feature, not gcc-only one.

I didn't ask you to replace the conditional, but to (possibly)
extend it.

Jan
Volodymyr Babchuk Oct. 11, 2017, 12:12 p.m. UTC | #4
Hi jan

On 11.10.17 11:07, Jan Beulich wrote:
>>>> On 10.10.17 at 19:03, <volodymyr_babchuk@epam.com> wrote:
>> On 10.10.17 19:12, Jan Beulich wrote:
>>>>>> On 10.10.17 at 17:52, <volodymyr_babchuk@epam.com> wrote:
>>>> +    uint8_t a[16];
>>>> +} xen_uuid_t;
>>>> +
>>>> +/*
>>>> + * XEN_DEFINE_UUID(0x00112233, 0x4455, 0x6677, 0x8899,
>>>> + *                 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff)
>>>> + * will construct UUID 00112233-4455-6677-8899-aabbccddeeff presented as
>>>> + * {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
>>>> + * 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
>>>> + *
>>>> + * NB: This is compatible with Linux kernel and with libuuid, but it is not
>>>> + * compatible with Microsoft, as they use mixed-endian encoding (some
>>>> + * components are little-endian, some are big-endian).
>>>> + */
>>>> +#define XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6)            \
>>>> +    {{((a) >> 24) & 0xFF, ((a) >> 16) & 0xFF,                           \
>>>> +      ((a) >>  8) & 0xFF, ((a) >>  0) & 0xFF,                           \
>>>> +      ((b) >>  8) & 0xFF, ((b) >>  0) & 0xFF,                           \
>>>> +      ((c) >>  8) & 0xFF, ((c) >>  0) & 0xFF,                           \
>>>> +      ((d) >>  8) & 0xFF, ((d) >>  0) & 0xFF,                           \
>>>> +                e1, e2, e3, e4, e5, e6}}
>>>> +
>>>> +/* Compound literals are supported in C99 and later. */
>>>> +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
>>>
>>> I didn't notice this earlier - why no check for __GNUC__?
>> I have seen pattern "#if defined (__STDC_VERSION__) && __STDC_VERSION__
> 
> But if you check, all of the existing ones have
> "#elif defined(__GNUC__)".
Yes. But there was a reason do to so. For example:

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
     uint32_t optarr[];
#elif defined(__GNUC__)
     uint32_t optarr[0];
#endif

(xen/include/public/physdev.h:303)

If compiler is C99 then we use flexible length array, else if compiller 
is GCC, we use zero-length array, which is GCC extension  (correct me). 
Other compilers (non-gcc C90 compatible) are not supported. Probably 
this is a bug.

Another case is even worse:

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
         unsigned char   buf[];
#elif defined(__GNUC__)
         unsigned char   buf[1]; /* OUT: Variable length buffer with 
build_id. */

(xen/include/public/version.h:49)

Array of length one is perfectly fine in any dialect of C. There are no 
need to check for GCC.
Also, again, this code will not define `buf` on non-gcc, C90 compatible 
compilers.

My code does not use gcc-only extensions like zero-length arrays, so I 
don't see how #elif defined (__GNUC__) can fit in the my case.


>>   >= 199901" in various places in XEN, so I did it alike.
>> Also, I'm using C99 feature, not gcc-only one.
> 
> I didn't ask you to replace the conditional, but to (possibly)
> extend it.
> 
> Jan
>
Jan Beulich Oct. 11, 2017, 12:23 p.m. UTC | #5
>>> On 11.10.17 at 14:12, <volodymyr_babchuk@epam.com> wrote:
> On 11.10.17 11:07, Jan Beulich wrote:
>>>>> On 10.10.17 at 19:03, <volodymyr_babchuk@epam.com> wrote:
>>> On 10.10.17 19:12, Jan Beulich wrote:
>>>>>>> On 10.10.17 at 17:52, <volodymyr_babchuk@epam.com> wrote:
>>>>> +    uint8_t a[16];
>>>>> +} xen_uuid_t;
>>>>> +
>>>>> +/*
>>>>> + * XEN_DEFINE_UUID(0x00112233, 0x4455, 0x6677, 0x8899,
>>>>> + *                 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff)
>>>>> + * will construct UUID 00112233-4455-6677-8899-aabbccddeeff presented as
>>>>> + * {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
>>>>> + * 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
>>>>> + *
>>>>> + * NB: This is compatible with Linux kernel and with libuuid, but it is not
>>>>> + * compatible with Microsoft, as they use mixed-endian encoding (some
>>>>> + * components are little-endian, some are big-endian).
>>>>> + */
>>>>> +#define XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6)            \
>>>>> +    {{((a) >> 24) & 0xFF, ((a) >> 16) & 0xFF,                           \
>>>>> +      ((a) >>  8) & 0xFF, ((a) >>  0) & 0xFF,                           \
>>>>> +      ((b) >>  8) & 0xFF, ((b) >>  0) & 0xFF,                           \
>>>>> +      ((c) >>  8) & 0xFF, ((c) >>  0) & 0xFF,                           \
>>>>> +      ((d) >>  8) & 0xFF, ((d) >>  0) & 0xFF,                           \
>>>>> +                e1, e2, e3, e4, e5, e6}}
>>>>> +
>>>>> +/* Compound literals are supported in C99 and later. */
>>>>> +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
>>>>
>>>> I didn't notice this earlier - why no check for __GNUC__?
>>> I have seen pattern "#if defined (__STDC_VERSION__) && __STDC_VERSION__
>> 
>> But if you check, all of the existing ones have
>> "#elif defined(__GNUC__)".
> Yes. But there was a reason do to so. For example:
> 
> #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
>      uint32_t optarr[];
> #elif defined(__GNUC__)
>      uint32_t optarr[0];
> #endif
> 
> (xen/include/public/physdev.h:303)
> 
> If compiler is C99 then we use flexible length array, else if compiller 
> is GCC, we use zero-length array, which is GCC extension  (correct me). 
> Other compilers (non-gcc C90 compatible) are not supported. Probably 
> this is a bug.

Why would that be a bug? In C89 you simply have no way to express
what we want, so people using plain C89 compilers will have to code
differently (i.e. without using the optarr field) anyway.

> Another case is even worse:
> 
> #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
>          unsigned char   buf[];
> #elif defined(__GNUC__)
>          unsigned char   buf[1]; /* OUT: Variable length buffer with 
> build_id. */
> 
> (xen/include/public/version.h:49)

That's not very reasonable indeed.

> My code does not use gcc-only extensions like zero-length arrays, so I 
> don't see how #elif defined (__GNUC__) can fit in the my case.

Did you check under what conditions the various gcc versions define
__STDC_VERSION__? Trying to compile

int test(void) {
	return __STDC_VERSION__;
}

with e.g. gcc 4.3.4 fails (with no other options specified). Otoh
even using -ansi compound literals compile fine.

Jan
diff mbox

Patch

diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h
index 2ac6b1e..1a6255f 100644
--- a/xen/include/public/xen.h
+++ b/xen/include/public/xen.h
@@ -930,6 +930,39 @@  __DEFINE_XEN_GUEST_HANDLE(uint16, uint16_t);
 __DEFINE_XEN_GUEST_HANDLE(uint32, uint32_t);
 __DEFINE_XEN_GUEST_HANDLE(uint64, uint64_t);
 
+typedef struct
+{
+    uint8_t a[16];
+} xen_uuid_t;
+
+/*
+ * XEN_DEFINE_UUID(0x00112233, 0x4455, 0x6677, 0x8899,
+ *                 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff)
+ * will construct UUID 00112233-4455-6677-8899-aabbccddeeff presented as
+ * {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
+ * 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
+ *
+ * NB: This is compatible with Linux kernel and with libuuid, but it is not
+ * compatible with Microsoft, as they use mixed-endian encoding (some
+ * components are little-endian, some are big-endian).
+ */
+#define XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6)            \
+    {{((a) >> 24) & 0xFF, ((a) >> 16) & 0xFF,                           \
+      ((a) >>  8) & 0xFF, ((a) >>  0) & 0xFF,                           \
+      ((b) >>  8) & 0xFF, ((b) >>  0) & 0xFF,                           \
+      ((c) >>  8) & 0xFF, ((c) >>  0) & 0xFF,                           \
+      ((d) >>  8) & 0xFF, ((d) >>  0) & 0xFF,                           \
+                e1, e2, e3, e4, e5, e6}}
+
+/* Compound literals are supported in C99 and later. */
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define XEN_DEFINE_UUID(a, b, c, d, e1, e2, e3, e4, e5, e6)             \
+    (xen_uuid_t)XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6)
+#else
+#define XEN_DEFINE_UUID(a, b, c, d, e1, e2, e3, e4, e5, e6)             \
+    XEN_DEFINE_UUID_(a, b, c, d, e1, e2, e3, e4, e5, e6)
+#endif /* defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L */
+
 #endif /* !__ASSEMBLY__ */
 
 /* Default definitions for macros used by domctl/sysctl. */