diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2008-05-02 22:50:49 -0400 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2008-05-02 07:50:50 -0400 |
commit | 72e61eb40b55dd57031ec5971e810649f82b0259 (patch) | |
tree | 66a836c7799b21156d4fc87f42e5817d7d95535b | |
parent | 5539ae9613587e4a4eec42d420b8bdd9ff552a65 (diff) |
virtio: change config to guest endian.
A recent proposed feature addition to the virtio block driver revealed
some flaws in the API, in particular how easy it is to break big
endian machines.
The virtio config space was originally chosen to be little-endian,
because we thought the config might be part of the PCI config space
for virtio_pci. It's actually a separate mmio region, so that
argument holds little water; as only x86 is currently using the virtio
mechanism, we can change this (but must do so now, before the
impending s390 merge).
API changes:
- __virtio_config_val() just becomes a striaght vdev->config_get() call.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | drivers/block/virtio_blk.c | 4 | ||||
-rw-r--r-- | drivers/virtio/virtio_balloon.c | 6 | ||||
-rw-r--r-- | include/linux/virtio_config.h | 47 |
3 files changed, 21 insertions, 36 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 7e83b6c6e3d6..cc6d39383a3f 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -246,8 +246,8 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
246 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); | 246 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); |
247 | 247 | ||
248 | /* Host must always specify the capacity. */ | 248 | /* Host must always specify the capacity. */ |
249 | __virtio_config_val(vdev, offsetof(struct virtio_blk_config, capacity), | 249 | vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity), |
250 | &cap); | 250 | &cap, sizeof(cap)); |
251 | 251 | ||
252 | /* If capacity is too big, truncate with warning. */ | 252 | /* If capacity is too big, truncate with warning. */ |
253 | if ((sector_t)cap != cap) { | 253 | if ((sector_t)cap != cap) { |
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 0b3efc31ee6d..fef88d84cef6 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
@@ -155,9 +155,9 @@ static void virtballoon_changed(struct virtio_device *vdev) | |||
155 | static inline s64 towards_target(struct virtio_balloon *vb) | 155 | static inline s64 towards_target(struct virtio_balloon *vb) |
156 | { | 156 | { |
157 | u32 v; | 157 | u32 v; |
158 | __virtio_config_val(vb->vdev, | 158 | vb->vdev->config->get(vb->vdev, |
159 | offsetof(struct virtio_balloon_config, num_pages), | 159 | offsetof(struct virtio_balloon_config, num_pages), |
160 | &v); | 160 | &v, sizeof(v)); |
161 | return v - vb->num_pages; | 161 | return v - vb->num_pages; |
162 | } | 162 | } |
163 | 163 | ||
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index d581b2914b34..475572e976fe 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h | |||
@@ -16,7 +16,7 @@ | |||
16 | #define VIRTIO_CONFIG_S_FAILED 0x80 | 16 | #define VIRTIO_CONFIG_S_FAILED 0x80 |
17 | 17 | ||
18 | #ifdef __KERNEL__ | 18 | #ifdef __KERNEL__ |
19 | struct virtio_device; | 19 | #include <linux/virtio.h> |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * virtio_config_ops - operations for configuring a virtio device | 22 | * virtio_config_ops - operations for configuring a virtio device |
@@ -30,13 +30,11 @@ struct virtio_device; | |||
30 | * offset: the offset of the configuration field | 30 | * offset: the offset of the configuration field |
31 | * buf: the buffer to write the field value into. | 31 | * buf: the buffer to write the field value into. |
32 | * len: the length of the buffer | 32 | * len: the length of the buffer |
33 | * Note that contents are conventionally little-endian. | ||
34 | * @set: write the value of a configuration field | 33 | * @set: write the value of a configuration field |
35 | * vdev: the virtio_device | 34 | * vdev: the virtio_device |
36 | * offset: the offset of the configuration field | 35 | * offset: the offset of the configuration field |
37 | * buf: the buffer to read the field value from. | 36 | * buf: the buffer to read the field value from. |
38 | * len: the length of the buffer | 37 | * len: the length of the buffer |
39 | * Note that contents are conventionally little-endian. | ||
40 | * @get_status: read the status byte | 38 | * @get_status: read the status byte |
41 | * vdev: the virtio_device | 39 | * vdev: the virtio_device |
42 | * Returns the status byte | 40 | * Returns the status byte |
@@ -70,40 +68,27 @@ struct virtio_config_ops | |||
70 | }; | 68 | }; |
71 | 69 | ||
72 | /** | 70 | /** |
73 | * virtio_config_val - look for a feature and get a single virtio config. | 71 | * virtio_config_val - look for a feature and get a virtio config entry. |
74 | * @vdev: the virtio device | 72 | * @vdev: the virtio device |
75 | * @fbit: the feature bit | 73 | * @fbit: the feature bit |
76 | * @offset: the type to search for. | 74 | * @offset: the type to search for. |
77 | * @val: a pointer to the value to fill in. | 75 | * @val: a pointer to the value to fill in. |
78 | * | 76 | * |
79 | * The return value is -ENOENT if the feature doesn't exist. Otherwise | 77 | * The return value is -ENOENT if the feature doesn't exist. Otherwise |
80 | * the value is endian-corrected and returned in v. */ | 78 | * the config value is copied into whatever is pointed to by v. */ |
81 | #define virtio_config_val(vdev, fbit, offset, v) ({ \ | 79 | #define virtio_config_val(vdev, fbit, offset, v) \ |
82 | int _err; \ | 80 | virtio_config_buf((vdev), (fbit), (offset), (v), sizeof(v)) |
83 | if ((vdev)->config->feature((vdev), (fbit))) { \ | ||
84 | __virtio_config_val((vdev), (offset), (v)); \ | ||
85 | _err = 0; \ | ||
86 | } else \ | ||
87 | _err = -ENOENT; \ | ||
88 | _err; \ | ||
89 | }) | ||
90 | 81 | ||
91 | /** | 82 | static inline int virtio_config_buf(struct virtio_device *vdev, |
92 | * __virtio_config_val - get a single virtio config without feature check. | 83 | unsigned int fbit, |
93 | * @vdev: the virtio device | 84 | unsigned int offset, |
94 | * @offset: the type to search for. | 85 | void *buf, unsigned len) |
95 | * @val: a pointer to the value to fill in. | 86 | { |
96 | * | 87 | if (!vdev->config->feature(vdev, fbit)) |
97 | * The value is endian-corrected and returned in v. */ | 88 | return -ENOENT; |
98 | #define __virtio_config_val(vdev, offset, v) do { \ | 89 | |
99 | BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2 \ | 90 | vdev->config->get(vdev, offset, buf, len); |
100 | && sizeof(*(v)) != 4 && sizeof(*(v)) != 8); \ | 91 | return 0; |
101 | (vdev)->config->get((vdev), (offset), (v), sizeof(*(v))); \ | 92 | } |
102 | switch (sizeof(*(v))) { \ | ||
103 | case 2: le16_to_cpus((__u16 *) v); break; \ | ||
104 | case 4: le32_to_cpus((__u32 *) v); break; \ | ||
105 | case 8: le64_to_cpus((__u64 *) v); break; \ | ||
106 | } \ | ||
107 | } while(0) | ||
108 | #endif /* __KERNEL__ */ | 93 | #endif /* __KERNEL__ */ |
109 | #endif /* _LINUX_VIRTIO_CONFIG_H */ | 94 | #endif /* _LINUX_VIRTIO_CONFIG_H */ |