Commit 5774cf98ca7da4161ee4265a2db0d92ffff005f3
Committed by
Anthony Liguori
1 parent
024431b3
virtio: make vring_desc_*() take phys addrs
Change the vring descriptor helpers to take the physical address of the descriptor table rather than a virtqueue. This is needed in order to allow these helpers to be used with an indirect descriptor table. Signed-off-by: Mark McLoughlin <markmc@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Showing
1 changed file
with
33 additions
and
26 deletions
hw/virtio.c
| @@ -85,31 +85,31 @@ static void virtqueue_init(VirtQueue *vq) | @@ -85,31 +85,31 @@ static void virtqueue_init(VirtQueue *vq) | ||
| 85 | VIRTIO_PCI_VRING_ALIGN); | 85 | VIRTIO_PCI_VRING_ALIGN); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | -static inline uint64_t vring_desc_addr(VirtQueue *vq, int i) | 88 | +static inline uint64_t vring_desc_addr(target_phys_addr_t desc_pa, int i) |
| 89 | { | 89 | { |
| 90 | target_phys_addr_t pa; | 90 | target_phys_addr_t pa; |
| 91 | - pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr); | 91 | + pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr); |
| 92 | return ldq_phys(pa); | 92 | return ldq_phys(pa); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | -static inline uint32_t vring_desc_len(VirtQueue *vq, int i) | 95 | +static inline uint32_t vring_desc_len(target_phys_addr_t desc_pa, int i) |
| 96 | { | 96 | { |
| 97 | target_phys_addr_t pa; | 97 | target_phys_addr_t pa; |
| 98 | - pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, len); | 98 | + pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, len); |
| 99 | return ldl_phys(pa); | 99 | return ldl_phys(pa); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | -static inline uint16_t vring_desc_flags(VirtQueue *vq, int i) | 102 | +static inline uint16_t vring_desc_flags(target_phys_addr_t desc_pa, int i) |
| 103 | { | 103 | { |
| 104 | target_phys_addr_t pa; | 104 | target_phys_addr_t pa; |
| 105 | - pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags); | 105 | + pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags); |
| 106 | return lduw_phys(pa); | 106 | return lduw_phys(pa); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | -static inline uint16_t vring_desc_next(VirtQueue *vq, int i) | 109 | +static inline uint16_t vring_desc_next(target_phys_addr_t desc_pa, int i) |
| 110 | { | 110 | { |
| 111 | target_phys_addr_t pa; | 111 | target_phys_addr_t pa; |
| 112 | - pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, next); | 112 | + pa = desc_pa + sizeof(VRingDesc) * i + offsetof(VRingDesc, next); |
| 113 | return lduw_phys(pa); | 113 | return lduw_phys(pa); |
| 114 | } | 114 | } |
| 115 | 115 | ||
| @@ -269,20 +269,21 @@ static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx) | @@ -269,20 +269,21 @@ static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx) | ||
| 269 | return head; | 269 | return head; |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | -static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i) | 272 | +static unsigned virtqueue_next_desc(target_phys_addr_t desc_pa, |
| 273 | + unsigned int i, unsigned int max) | ||
| 273 | { | 274 | { |
| 274 | unsigned int next; | 275 | unsigned int next; |
| 275 | 276 | ||
| 276 | /* If this descriptor says it doesn't chain, we're done. */ | 277 | /* If this descriptor says it doesn't chain, we're done. */ |
| 277 | - if (!(vring_desc_flags(vq, i) & VRING_DESC_F_NEXT)) | ||
| 278 | - return vq->vring.num; | 278 | + if (!(vring_desc_flags(desc_pa, i) & VRING_DESC_F_NEXT)) |
| 279 | + return max; | ||
| 279 | 280 | ||
| 280 | /* Check they're not leading us off end of descriptors. */ | 281 | /* Check they're not leading us off end of descriptors. */ |
| 281 | - next = vring_desc_next(vq, i); | 282 | + next = vring_desc_next(desc_pa, i); |
| 282 | /* Make sure compiler knows to grab that: we don't want it changing! */ | 283 | /* Make sure compiler knows to grab that: we don't want it changing! */ |
| 283 | wmb(); | 284 | wmb(); |
| 284 | 285 | ||
| 285 | - if (next >= vq->vring.num) { | 286 | + if (next >= max) { |
| 286 | fprintf(stderr, "Desc next is %u", next); | 287 | fprintf(stderr, "Desc next is %u", next); |
| 287 | exit(1); | 288 | exit(1); |
| 288 | } | 289 | } |
| @@ -292,10 +293,12 @@ static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i) | @@ -292,10 +293,12 @@ static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i) | ||
| 292 | 293 | ||
| 293 | int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) | 294 | int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) |
| 294 | { | 295 | { |
| 295 | - unsigned int idx; | 296 | + target_phys_addr_t desc_pa = vq->vring.desc; |
| 297 | + unsigned int idx, max; | ||
| 296 | int num_bufs, in_total, out_total; | 298 | int num_bufs, in_total, out_total; |
| 297 | 299 | ||
| 298 | idx = vq->last_avail_idx; | 300 | idx = vq->last_avail_idx; |
| 301 | + max = vq->vring.num; | ||
| 299 | 302 | ||
| 300 | num_bufs = in_total = out_total = 0; | 303 | num_bufs = in_total = out_total = 0; |
| 301 | while (virtqueue_num_heads(vq, idx)) { | 304 | while (virtqueue_num_heads(vq, idx)) { |
| @@ -304,21 +307,21 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) | @@ -304,21 +307,21 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) | ||
| 304 | i = virtqueue_get_head(vq, idx++); | 307 | i = virtqueue_get_head(vq, idx++); |
| 305 | do { | 308 | do { |
| 306 | /* If we've got too many, that implies a descriptor loop. */ | 309 | /* If we've got too many, that implies a descriptor loop. */ |
| 307 | - if (++num_bufs > vq->vring.num) { | 310 | + if (++num_bufs > max) { |
| 308 | fprintf(stderr, "Looped descriptor"); | 311 | fprintf(stderr, "Looped descriptor"); |
| 309 | exit(1); | 312 | exit(1); |
| 310 | } | 313 | } |
| 311 | 314 | ||
| 312 | - if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) { | 315 | + if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) { |
| 313 | if (in_bytes > 0 && | 316 | if (in_bytes > 0 && |
| 314 | - (in_total += vring_desc_len(vq, i)) >= in_bytes) | 317 | + (in_total += vring_desc_len(desc_pa, i)) >= in_bytes) |
| 315 | return 1; | 318 | return 1; |
| 316 | } else { | 319 | } else { |
| 317 | if (out_bytes > 0 && | 320 | if (out_bytes > 0 && |
| 318 | - (out_total += vring_desc_len(vq, i)) >= out_bytes) | 321 | + (out_total += vring_desc_len(desc_pa, i)) >= out_bytes) |
| 319 | return 1; | 322 | return 1; |
| 320 | } | 323 | } |
| 321 | - } while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num); | 324 | + } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max); |
| 322 | } | 325 | } |
| 323 | 326 | ||
| 324 | return 0; | 327 | return 0; |
| @@ -326,7 +329,8 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) | @@ -326,7 +329,8 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) | ||
| 326 | 329 | ||
| 327 | int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) | 330 | int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) |
| 328 | { | 331 | { |
| 329 | - unsigned int i, head; | 332 | + unsigned int i, head, max; |
| 333 | + target_phys_addr_t desc_pa = vq->vring.desc; | ||
| 330 | target_phys_addr_t len; | 334 | target_phys_addr_t len; |
| 331 | 335 | ||
| 332 | if (!virtqueue_num_heads(vq, vq->last_avail_idx)) | 336 | if (!virtqueue_num_heads(vq, vq->last_avail_idx)) |
| @@ -335,23 +339,26 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) | @@ -335,23 +339,26 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) | ||
| 335 | /* When we start there are none of either input nor output. */ | 339 | /* When we start there are none of either input nor output. */ |
| 336 | elem->out_num = elem->in_num = 0; | 340 | elem->out_num = elem->in_num = 0; |
| 337 | 341 | ||
| 342 | + max = vq->vring.num; | ||
| 343 | + | ||
| 338 | i = head = virtqueue_get_head(vq, vq->last_avail_idx++); | 344 | i = head = virtqueue_get_head(vq, vq->last_avail_idx++); |
| 339 | do { | 345 | do { |
| 340 | struct iovec *sg; | 346 | struct iovec *sg; |
| 341 | int is_write = 0; | 347 | int is_write = 0; |
| 342 | 348 | ||
| 343 | - if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) { | ||
| 344 | - elem->in_addr[elem->in_num] = vring_desc_addr(vq, i); | 349 | + if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) { |
| 350 | + elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i); | ||
| 345 | sg = &elem->in_sg[elem->in_num++]; | 351 | sg = &elem->in_sg[elem->in_num++]; |
| 346 | is_write = 1; | 352 | is_write = 1; |
| 347 | } else | 353 | } else |
| 348 | sg = &elem->out_sg[elem->out_num++]; | 354 | sg = &elem->out_sg[elem->out_num++]; |
| 349 | 355 | ||
| 350 | /* Grab the first descriptor, and check it's OK. */ | 356 | /* Grab the first descriptor, and check it's OK. */ |
| 351 | - sg->iov_len = vring_desc_len(vq, i); | 357 | + sg->iov_len = vring_desc_len(desc_pa, i); |
| 352 | len = sg->iov_len; | 358 | len = sg->iov_len; |
| 353 | 359 | ||
| 354 | - sg->iov_base = cpu_physical_memory_map(vring_desc_addr(vq, i), &len, is_write); | 360 | + sg->iov_base = cpu_physical_memory_map(vring_desc_addr(desc_pa, i), |
| 361 | + &len, is_write); | ||
| 355 | 362 | ||
| 356 | if (sg->iov_base == NULL || len != sg->iov_len) { | 363 | if (sg->iov_base == NULL || len != sg->iov_len) { |
| 357 | fprintf(stderr, "virtio: trying to map MMIO memory\n"); | 364 | fprintf(stderr, "virtio: trying to map MMIO memory\n"); |
| @@ -359,11 +366,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) | @@ -359,11 +366,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) | ||
| 359 | } | 366 | } |
| 360 | 367 | ||
| 361 | /* If we've got too many, that implies a descriptor loop. */ | 368 | /* If we've got too many, that implies a descriptor loop. */ |
| 362 | - if ((elem->in_num + elem->out_num) > vq->vring.num) { | 369 | + if ((elem->in_num + elem->out_num) > max) { |
| 363 | fprintf(stderr, "Looped descriptor"); | 370 | fprintf(stderr, "Looped descriptor"); |
| 364 | exit(1); | 371 | exit(1); |
| 365 | } | 372 | } |
| 366 | - } while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num); | 373 | + } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max); |
| 367 | 374 | ||
| 368 | elem->index = head; | 375 | elem->index = head; |
| 369 | 376 |