Commit a5b90f2d authored by Michael S. Tsirkin's avatar Michael S. Tsirkin

virtio_config: rewrite using _Generic

Min compiler version has been raised, so that's ok now.
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent cacaf775
...@@ -288,112 +288,103 @@ static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val) ...@@ -288,112 +288,103 @@ static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
return __cpu_to_virtio64(virtio_is_little_endian(vdev), val); return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
} }
/* #define virtio_to_cpu(vdev, x) \
* Only the checker differentiates between __virtioXX and __uXX types. But we _Generic((x), \
* try to share as much code as we can with the regular GCC build. __u8: (x), \
*/ __virtio16: virtio16_to_cpu((vdev), (x)), \
#if !defined(CONFIG_CC_IS_GCC) && !defined(__CHECKER__) __virtio32: virtio32_to_cpu((vdev), (x)), \
__virtio64: virtio64_to_cpu((vdev), (x)), \
/* Not a checker - we can keep things simple */ /*
#define __virtio_native_typeof(x) typeof(x) * Why define a default? checker can distinguish between
* e.g. __u16, __le16 and __virtio16, but GCC can't so
#else * attempts to define variants for both look like a duplicate
* variant to it.
/* */ \
* We build this out of a couple of helper macros in a vain attempt to default: _Generic((x), \
* help you keep your lunch down while reading it. __u8: (x), \
*/ __le16: virtio16_to_cpu((vdev), (__force __virtio16)(x)), \
#define __virtio_pick_value(x, type, then, otherwise) \ __le32: virtio32_to_cpu((vdev), (__force __virtio32)(x)), \
__builtin_choose_expr(__same_type(x, type), then, otherwise) __le64: virtio64_to_cpu((vdev), (__force __virtio64)(x)), \
default: _Generic((x), \
#define __virtio_pick_type(x, type, then, otherwise) \ __u8: (x), \
__virtio_pick_value(x, type, (then)0, otherwise) __u16: virtio16_to_cpu((vdev), (__force __virtio16)(x)), \
__u32: virtio32_to_cpu((vdev), (__force __virtio32)(x)), \
#define __virtio_pick_endian(x, x16, x32, x64, otherwise) \ __u64: virtio64_to_cpu((vdev), (__force __virtio64)(x)) \
__virtio_pick_type(x, x16, __u16, \ ) \
__virtio_pick_type(x, x32, __u32, \ ) \
__virtio_pick_type(x, x64, __u64, \ )
otherwise)))
#define cpu_to_virtio(vdev, x, m) \
#define __virtio_native_typeof(x) typeof( \ _Generic((m), \
__virtio_pick_type(x, __u8, __u8, \ __u8: (x), \
__virtio_pick_endian(x, __virtio16, __virtio32, __virtio64, \ __virtio16: cpu_to_virtio16((vdev), (x)), \
__virtio_pick_endian(x, __le16, __le32, __le64, \ __virtio32: cpu_to_virtio32((vdev), (x)), \
/* No other type allowed */ \ __virtio64: cpu_to_virtio64((vdev), (x)), \
(void)0)))) /*
* Why define a default? checker can distinguish between
#endif * e.g. __u16, __le16 and __virtio16, but GCC can't so
* attempts to define variants for both look like a duplicate
* variant to it.
*/ \
default: _Generic((m), \
__u8: (x), \
__le16: (__force __le16)cpu_to_virtio16((vdev), (x)), \
__le32: (__force __le32)cpu_to_virtio32((vdev), (x)), \
__le64: (__force __le64)cpu_to_virtio64((vdev), (x)), \
default: _Generic((m), \
__u8: (x), \
__u16: (__force __u16)cpu_to_virtio16((vdev), (x)), \
__u32: (__force __u32)cpu_to_virtio32((vdev), (x)), \
__u64: (__force __u64)cpu_to_virtio64((vdev), (x)) \
) \
) \
)
#define __virtio_native_type(structname, member) \ #define __virtio_native_type(structname, member) \
__virtio_native_typeof(((structname*)0)->member) typeof(virtio_to_cpu(NULL, ((structname*)0)->member))
#define __virtio_typecheck(structname, member, val) \
/* Must match the member's type, and be integer */ \
typecheck(__virtio_native_type(structname, member), (val))
/* Config space accessors. */ /* Config space accessors. */
#define virtio_cread(vdev, structname, member, ptr) \ #define virtio_cread(vdev, structname, member, ptr) \
do { \ do { \
typeof(((structname*)0)->member) virtio_cread_v; \
\
might_sleep(); \ might_sleep(); \
/* Must match the member's type, and be integer */ \ /* Sanity check: must match the member's type */ \
if (!__virtio_typecheck(structname, member, *(ptr))) \ typecheck(typeof(virtio_to_cpu((vdev), virtio_cread_v)), *(ptr)); \
(*ptr) = 1; \
\ \
switch (sizeof(*ptr)) { \ switch (sizeof(virtio_cread_v)) { \
case 1: \ case 1: \
*(ptr) = virtio_cread8(vdev, \
offsetof(structname, member)); \
break; \
case 2: \ case 2: \
*(ptr) = virtio_cread16(vdev, \
offsetof(structname, member)); \
break; \
case 4: \ case 4: \
*(ptr) = virtio_cread32(vdev, \ vdev->config->get((vdev), \
offsetof(structname, member)); \ offsetof(structname, member), \
break; \ &virtio_cread_v, \
case 8: \ sizeof(virtio_cread_v)); \
*(ptr) = virtio_cread64(vdev, \
offsetof(structname, member)); \
break; \ break; \
default: \ default: \
BUG(); \ __virtio_cread_many((vdev), \
offsetof(structname, member), \
&virtio_cread_v, \
1, \
sizeof(virtio_cread_v)); \
break; \
} \ } \
*(ptr) = virtio_to_cpu(vdev, virtio_cread_v); \
} while(0) } while(0)
/* Config space accessors. */ /* Config space accessors. */
#define virtio_cwrite(vdev, structname, member, ptr) \ #define virtio_cwrite(vdev, structname, member, ptr) \
do { \ do { \
typeof(((structname*)0)->member) virtio_cwrite_v = \
cpu_to_virtio(vdev, *(ptr), ((structname*)0)->member); \
\
might_sleep(); \ might_sleep(); \
/* Must match the member's type, and be integer */ \ /* Sanity check: must match the member's type */ \
if (!__virtio_typecheck(structname, member, *(ptr))) \ typecheck(typeof(virtio_to_cpu((vdev), virtio_cwrite_v)), *(ptr)); \
BUG_ON((*ptr) == 1); \
\ \
switch (sizeof(*ptr)) { \ vdev->config->set((vdev), offsetof(structname, member), \
case 1: \ &virtio_cwrite_v, \
virtio_cwrite8(vdev, \ sizeof(virtio_cwrite_v)); \
offsetof(structname, member), \
*(ptr)); \
break; \
case 2: \
virtio_cwrite16(vdev, \
offsetof(structname, member), \
*(ptr)); \
break; \
case 4: \
virtio_cwrite32(vdev, \
offsetof(structname, member), \
*(ptr)); \
break; \
case 8: \
virtio_cwrite64(vdev, \
offsetof(structname, member), \
*(ptr)); \
break; \
default: \
BUG(); \
} \
} while(0) } while(0)
/* Read @count fields, @bytes each. */ /* Read @count fields, @bytes each. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment