Commit 26b258e13860a885b337cf7564162b93894863e4
1 parent
d28a1b6e
Use the DMA api to map virtio elements.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6904 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
17 additions
and
82 deletions
hw/virtio.c
| ... | ... | @@ -16,8 +16,6 @@ |
| 16 | 16 | #include "virtio.h" |
| 17 | 17 | #include "sysemu.h" |
| 18 | 18 | |
| 19 | -//#define VIRTIO_ZERO_COPY | |
| 20 | - | |
| 21 | 19 | /* from Linux's linux/virtio_pci.h */ |
| 22 | 20 | |
| 23 | 21 | /* A 32-bit r/o bitmask of the features supported by the host */ |
| ... | ... | @@ -113,43 +111,6 @@ struct VirtQueue |
| 113 | 111 | #define VIRTIO_PCI_QUEUE_MAX 16 |
| 114 | 112 | |
| 115 | 113 | /* virt queue functions */ |
| 116 | -#ifdef VIRTIO_ZERO_COPY | |
| 117 | -static void *virtio_map_gpa(target_phys_addr_t addr, size_t size) | |
| 118 | -{ | |
| 119 | - ram_addr_t off; | |
| 120 | - target_phys_addr_t addr1; | |
| 121 | - | |
| 122 | - off = cpu_get_physical_page_desc(addr); | |
| 123 | - if ((off & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { | |
| 124 | - fprintf(stderr, "virtio DMA to IO ram\n"); | |
| 125 | - exit(1); | |
| 126 | - } | |
| 127 | - | |
| 128 | - off = (off & TARGET_PAGE_MASK) | (addr & ~TARGET_PAGE_MASK); | |
| 129 | - | |
| 130 | - for (addr1 = addr + TARGET_PAGE_SIZE; | |
| 131 | - addr1 < TARGET_PAGE_ALIGN(addr + size); | |
| 132 | - addr1 += TARGET_PAGE_SIZE) { | |
| 133 | - ram_addr_t off1; | |
| 134 | - | |
| 135 | - off1 = cpu_get_physical_page_desc(addr1); | |
| 136 | - if ((off1 & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { | |
| 137 | - fprintf(stderr, "virtio DMA to IO ram\n"); | |
| 138 | - exit(1); | |
| 139 | - } | |
| 140 | - | |
| 141 | - off1 = (off1 & TARGET_PAGE_MASK) | (addr1 & ~TARGET_PAGE_MASK); | |
| 142 | - | |
| 143 | - if (off1 != (off + (addr1 - addr))) { | |
| 144 | - fprintf(stderr, "discontigous virtio memory\n"); | |
| 145 | - exit(1); | |
| 146 | - } | |
| 147 | - } | |
| 148 | - | |
| 149 | - return phys_ram_base + off; | |
| 150 | -} | |
| 151 | -#endif | |
| 152 | - | |
| 153 | 114 | static void virtqueue_init(VirtQueue *vq, target_phys_addr_t pa) |
| 154 | 115 | { |
| 155 | 116 | vq->vring.desc = pa; |
| ... | ... | @@ -274,35 +235,22 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, |
| 274 | 235 | unsigned int offset; |
| 275 | 236 | int i; |
| 276 | 237 | |
| 277 | -#ifndef VIRTIO_ZERO_COPY | |
| 278 | - for (i = 0; i < elem->out_num; i++) | |
| 279 | - qemu_free(elem->out_sg[i].iov_base); | |
| 280 | -#endif | |
| 281 | - | |
| 282 | 238 | offset = 0; |
| 283 | 239 | for (i = 0; i < elem->in_num; i++) { |
| 284 | 240 | size_t size = MIN(len - offset, elem->in_sg[i].iov_len); |
| 285 | 241 | |
| 286 | -#ifdef VIRTIO_ZERO_COPY | |
| 287 | - if (size) { | |
| 288 | - ram_addr_t addr = (uint8_t *)elem->in_sg[i].iov_base - phys_ram_base; | |
| 289 | - ram_addr_t off; | |
| 242 | + cpu_physical_memory_unmap(elem->in_sg[i].iov_base, | |
| 243 | + elem->in_sg[i].iov_len, | |
| 244 | + 1, size); | |
| 290 | 245 | |
| 291 | - for (off = 0; off < size; off += TARGET_PAGE_SIZE) | |
| 292 | - cpu_physical_memory_set_dirty(addr + off); | |
| 293 | - } | |
| 294 | -#else | |
| 295 | - if (size) | |
| 296 | - cpu_physical_memory_write(elem->in_addr[i], | |
| 297 | - elem->in_sg[i].iov_base, | |
| 298 | - size); | |
| 299 | - | |
| 300 | - qemu_free(elem->in_sg[i].iov_base); | |
| 301 | -#endif | |
| 302 | - | |
| 303 | - offset += size; | |
| 246 | + offset += elem->in_sg[i].iov_len; | |
| 304 | 247 | } |
| 305 | 248 | |
| 249 | + for (i = 0; i < elem->out_num; i++) | |
| 250 | + cpu_physical_memory_unmap(elem->out_sg[i].iov_base, | |
| 251 | + elem->out_sg[i].iov_len, | |
| 252 | + 0, elem->out_sg[i].iov_len); | |
| 253 | + | |
| 306 | 254 | idx = (idx + vring_used_idx(vq)) % vq->vring.num; |
| 307 | 255 | |
| 308 | 256 | /* Get a pointer to the next entry in the used ring. */ |
| ... | ... | @@ -414,6 +362,7 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes) |
| 414 | 362 | int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) |
| 415 | 363 | { |
| 416 | 364 | unsigned int i, head; |
| 365 | + target_phys_addr_t len; | |
| 417 | 366 | |
| 418 | 367 | if (!virtqueue_num_heads(vq, vq->last_avail_idx)) |
| 419 | 368 | return 0; |
| ... | ... | @@ -424,37 +373,23 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem) |
| 424 | 373 | i = head = virtqueue_get_head(vq, vq->last_avail_idx++); |
| 425 | 374 | do { |
| 426 | 375 | struct iovec *sg; |
| 376 | + int is_write = 0; | |
| 427 | 377 | |
| 428 | 378 | if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) { |
| 429 | 379 | elem->in_addr[elem->in_num] = vring_desc_addr(vq, i); |
| 430 | 380 | sg = &elem->in_sg[elem->in_num++]; |
| 381 | + is_write = 1; | |
| 431 | 382 | } else |
| 432 | 383 | sg = &elem->out_sg[elem->out_num++]; |
| 433 | 384 | |
| 434 | 385 | /* Grab the first descriptor, and check it's OK. */ |
| 435 | 386 | sg->iov_len = vring_desc_len(vq, i); |
| 387 | + len = sg->iov_len; | |
| 436 | 388 | |
| 437 | -#ifdef VIRTIO_ZERO_COPY | |
| 438 | - sg->iov_base = virtio_map_gpa(vring_desc_addr(vq, i), sg->iov_len); | |
| 439 | -#else | |
| 440 | - /* cap individual scatter element size to prevent unbounded allocations | |
| 441 | - of memory from the guest. Practically speaking, no virtio driver | |
| 442 | - will ever pass more than a page in each element. We set the cap to | |
| 443 | - be 2MB in case for some reason a large page makes it way into the | |
| 444 | - sg list. When we implement a zero copy API, this limitation will | |
| 445 | - disappear */ | |
| 446 | - if (sg->iov_len > (2 << 20)) | |
| 447 | - sg->iov_len = 2 << 20; | |
| 448 | - | |
| 449 | - sg->iov_base = qemu_malloc(sg->iov_len); | |
| 450 | - if (!(vring_desc_flags(vq, i) & VRING_DESC_F_WRITE)) { | |
| 451 | - cpu_physical_memory_read(vring_desc_addr(vq, i), | |
| 452 | - sg->iov_base, | |
| 453 | - sg->iov_len); | |
| 454 | - } | |
| 455 | -#endif | |
| 456 | - if (sg->iov_base == NULL) { | |
| 457 | - fprintf(stderr, "Invalid mapping\n"); | |
| 389 | + sg->iov_base = cpu_physical_memory_map(vring_desc_addr(vq, i), &len, is_write); | |
| 390 | + | |
| 391 | + if (sg->iov_base == NULL || len != sg->iov_len) { | |
| 392 | + fprintf(stderr, "virtio: trying to map MMIO memory\n"); | |
| 458 | 393 | exit(1); |
| 459 | 394 | } |
| 460 | 395 | ... | ... |