Skip to content

Commit 277c7e1

Browse files
otterycshengwen-tw
andcommitted
Rectify length of Virtio descriptor address
According to Virtio Specification Version 1.3, Section 2.7.5 *The Virtqueue Descriptor Table*, the type of 'addr' should be 'uint64_t' instead of 'uint32_t'. This commit addresses the error in the previous implementation. Co-authored-by: Shengwen Cheng <[email protected]>
1 parent d61c9f6 commit 277c7e1

File tree

4 files changed

+42
-43
lines changed

4 files changed

+42
-43
lines changed

virtio-blk.c

+9-7
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ static void virtio_blk_update_status(virtio_blk_state_t *vblk, uint32_t status)
102102

103103
static void virtio_blk_write_handler(virtio_blk_state_t *vblk,
104104
uint64_t sector,
105-
uint32_t desc_addr,
105+
uint64_t desc_addr,
106106
uint32_t len)
107107
{
108108
void *dest = (void *) ((uintptr_t) vblk->disk + sector * DISK_BLK_SIZE);
@@ -112,7 +112,7 @@ static void virtio_blk_write_handler(virtio_blk_state_t *vblk,
112112

113113
static void virtio_blk_read_handler(virtio_blk_state_t *vblk,
114114
uint64_t sector,
115-
uint32_t desc_addr,
115+
uint64_t desc_addr,
116116
uint32_t len)
117117
{
118118
void *dest = (void *) ((uintptr_t) vblk->ram + desc_addr);
@@ -141,13 +141,15 @@ static int virtio_blk_desc_handler(virtio_blk_state_t *vblk,
141141
/* Collect the descriptors */
142142
for (int i = 0; i < 3; i++) {
143143
/* The size of the `struct virtq_desc` is 4 words */
144-
const uint32_t *desc = &vblk->ram[queue->QueueDesc + desc_idx * 4];
144+
const struct virtq_desc *desc =
145+
(struct virtq_desc *) &vblk->ram[queue->QueueDesc + desc_idx * 4];
146+
145147

146148
/* Retrieve the fields of current descriptor */
147-
vq_desc[i].addr = desc[0];
148-
vq_desc[i].len = desc[2];
149-
vq_desc[i].flags = desc[3];
150-
desc_idx = desc[3] >> 16; /* vq_desc[desc_cnt].next */
149+
vq_desc[i].addr = desc->addr;
150+
vq_desc[i].len = desc->len;
151+
vq_desc[i].flags = desc->flags;
152+
desc_idx = desc->next;
151153
}
152154

153155
/* The next flag for the first and second descriptors should be set,

virtio-net.c

+25-24
Original file line numberDiff line numberDiff line change
@@ -180,35 +180,36 @@ static ssize_t handle_write(netdev_t *netdev,
180180
/* Require existing 'desc_idx' to use as iteration variable, and input
181181
* 'buffer_idx'.
182182
*/
183-
#define VNET_ITERATE_BUFFER(checked, body) \
184-
desc_idx = buffer_idx; \
185-
while (1) { \
186-
if (checked && desc_idx >= queue->QueueNum) \
187-
return virtio_net_set_fail(vnet); \
188-
const uint32_t *desc = &ram[queue->QueueDesc + desc_idx * 4]; \
189-
uint16_t desc_flags = desc[3]; \
190-
body if (!(desc_flags & VIRTIO_DESC_F_NEXT)) break; \
191-
desc_idx = desc[3] >> 16; \
183+
#define VNET_ITERATE_BUFFER(checked, body) \
184+
desc_idx = buffer_idx; \
185+
while (1) { \
186+
if (checked && desc_idx >= queue->QueueNum) \
187+
return virtio_net_set_fail(vnet); \
188+
const struct virtq_desc *desc = \
189+
(struct virtq_desc *) &ram[queue->QueueDesc + desc_idx * 4]; \
190+
uint16_t desc_flags = desc->flags; \
191+
body if (!(desc_flags & VIRTIO_DESC_F_NEXT)) break; \
192+
desc_idx = desc->next; \
192193
}
193194

194195
/* Input: 'buffer_idx'.
195196
* Output: 'buffer_niovs' and 'buffer_iovs'
196197
*/
197-
#define VNET_BUFFER_TO_IOV(expect_readable) \
198-
uint16_t desc_idx; \
199-
/* do a first pass to validate flags and count buffers */ \
200-
size_t buffer_niovs = 0; \
201-
VNET_ITERATE_BUFFER( \
202-
true, if ((!!(desc_flags & VIRTIO_DESC_F_WRITE)) != \
203-
(expect_readable)) return virtio_net_set_fail(vnet); \
204-
buffer_niovs++;) \
205-
/* convert to iov */ \
206-
struct iovec buffer_iovs[buffer_niovs]; \
207-
buffer_niovs = 0; \
208-
VNET_ITERATE_BUFFER( \
209-
false, uint32_t desc_addr = desc[0]; uint32_t desc_len = desc[2]; \
210-
buffer_iovs[buffer_niovs].iov_base = \
211-
(void *) ((uintptr_t) ram + desc_addr); \
198+
#define VNET_BUFFER_TO_IOV(expect_readable) \
199+
uint16_t desc_idx; \
200+
/* do a first pass to validate flags and count buffers */ \
201+
size_t buffer_niovs = 0; \
202+
VNET_ITERATE_BUFFER( \
203+
true, if ((!!(desc_flags & VIRTIO_DESC_F_WRITE)) != \
204+
(expect_readable)) return virtio_net_set_fail(vnet); \
205+
buffer_niovs++;) \
206+
/* convert to iov */ \
207+
struct iovec buffer_iovs[buffer_niovs]; \
208+
buffer_niovs = 0; \
209+
VNET_ITERATE_BUFFER( \
210+
false, uint64_t desc_addr = desc->addr; uint32_t desc_len = desc->len; \
211+
buffer_iovs[buffer_niovs].iov_base = \
212+
(void *) ((uintptr_t) ram + desc_addr); \
212213
buffer_iovs[buffer_niovs].iov_len = desc_len; buffer_niovs++;)
213214

214215
#define VNET_GENERATE_QUEUE_HANDLER(NAME_SUFFIX, VERB, QUEUE_IDX, READ) \

virtio-rng.c

+5-9
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,16 @@ static void virtio_queue_notify_handler(virtio_rng_state_t *vrng,
6161
VRNG_QUEUE.last_avail++;
6262

6363
/* Read descriptor */
64-
uint32_t *desc = &vrng->ram[queue->QueueDesc + buffer_idx * 4];
65-
struct virtq_desc vq_desc = {
66-
.addr = desc[0],
67-
.len = desc[2],
68-
.flags = desc[3],
69-
};
64+
struct virtq_desc *vq_desc =
65+
(struct virtq_desc *) &vrng->ram[queue->QueueDesc + buffer_idx * 4];
7066

7167
/* Write entropy buffer */
7268
void *entropy_buf =
73-
(void *) ((uintptr_t) vrng->ram + (uintptr_t) vq_desc.addr);
74-
ssize_t total = read(rng_fd, entropy_buf, vq_desc.len);
69+
(void *) ((uintptr_t) vrng->ram + (uintptr_t) vq_desc->addr);
70+
ssize_t total = read(rng_fd, entropy_buf, vq_desc->len);
7571

7672
/* Clear write flag */
77-
desc[3] = 0;
73+
vq_desc->flags = 0;
7874

7975
/* Get virtq_used.idx (le16) */
8076
uint16_t used = ram[queue->QueueUsed] >> 16;

virtio.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ enum {
5757
#undef _
5858
};
5959

60-
struct virtq_desc {
61-
uint32_t addr;
60+
PACKED(struct virtq_desc {
61+
uint64_t addr;
6262
uint32_t len;
6363
uint16_t flags;
6464
uint16_t next;
65-
};
65+
});

0 commit comments

Comments
 (0)