Revision cb06608e hw/ivshmem.c
b/hw/ivshmem.c | ||
---|---|---|
56 | 56 |
|
57 | 57 |
CharDriverState **eventfd_chr; |
58 | 58 |
CharDriverState *server_chr; |
59 |
int ivshmem_mmio_io_addr;
|
|
59 |
MemoryRegion ivshmem_mmio;
|
|
60 | 60 |
|
61 | 61 |
pcibus_t mmio_addr; |
62 |
pcibus_t shm_pci_addr; |
|
63 |
uint64_t ivshmem_offset; |
|
62 |
/* We might need to register the BAR before we actually have the memory. |
|
63 |
* So prepare a container MemoryRegion for the BAR immediately and |
|
64 |
* add a subregion when we have the memory. |
|
65 |
*/ |
|
66 |
MemoryRegion bar; |
|
67 |
MemoryRegion ivshmem; |
|
64 | 68 |
uint64_t ivshmem_size; /* size of shared memory region */ |
65 | 69 |
int shm_fd; /* shared memory file descriptor */ |
66 | 70 |
|
... | ... | |
96 | 100 |
return (x & (x - 1)) == 0; |
97 | 101 |
} |
98 | 102 |
|
99 |
static void ivshmem_map(PCIDevice *pci_dev, int region_num, |
|
100 |
pcibus_t addr, pcibus_t size, int type) |
|
101 |
{ |
|
102 |
IVShmemState *s = DO_UPCAST(IVShmemState, dev, pci_dev); |
|
103 |
|
|
104 |
s->shm_pci_addr = addr; |
|
105 |
|
|
106 |
if (s->ivshmem_offset > 0) { |
|
107 |
cpu_register_physical_memory(s->shm_pci_addr, s->ivshmem_size, |
|
108 |
s->ivshmem_offset); |
|
109 |
} |
|
110 |
|
|
111 |
IVSHMEM_DPRINTF("guest pci addr = %" FMT_PCIBUS ", guest h/w addr = %" |
|
112 |
PRIu64 ", size = %" FMT_PCIBUS "\n", addr, s->ivshmem_offset, size); |
|
113 |
|
|
114 |
} |
|
115 |
|
|
116 | 103 |
/* accessing registers - based on rtl8139 */ |
117 | 104 |
static void ivshmem_update_irq(IVShmemState *s, int val) |
118 | 105 |
{ |
... | ... | |
168 | 155 |
return ret; |
169 | 156 |
} |
170 | 157 |
|
171 |
static void ivshmem_io_writew(void *opaque, target_phys_addr_t addr, |
|
172 |
uint32_t val) |
|
173 |
{ |
|
174 |
|
|
175 |
IVSHMEM_DPRINTF("We shouldn't be writing words\n"); |
|
176 |
} |
|
177 |
|
|
178 |
static void ivshmem_io_writel(void *opaque, target_phys_addr_t addr, |
|
179 |
uint32_t val) |
|
158 |
static void ivshmem_io_write(void *opaque, target_phys_addr_t addr, |
|
159 |
uint64_t val, unsigned size) |
|
180 | 160 |
{ |
181 | 161 |
IVShmemState *s = opaque; |
182 | 162 |
|
... | ... | |
219 | 199 |
} |
220 | 200 |
} |
221 | 201 |
|
222 |
static void ivshmem_io_writeb(void *opaque, target_phys_addr_t addr, |
|
223 |
uint32_t val) |
|
224 |
{ |
|
225 |
IVSHMEM_DPRINTF("We shouldn't be writing bytes\n"); |
|
226 |
} |
|
227 |
|
|
228 |
static uint32_t ivshmem_io_readw(void *opaque, target_phys_addr_t addr) |
|
229 |
{ |
|
230 |
|
|
231 |
IVSHMEM_DPRINTF("We shouldn't be reading words\n"); |
|
232 |
return 0; |
|
233 |
} |
|
234 |
|
|
235 |
static uint32_t ivshmem_io_readl(void *opaque, target_phys_addr_t addr) |
|
202 |
static uint64_t ivshmem_io_read(void *opaque, target_phys_addr_t addr, |
|
203 |
unsigned size) |
|
236 | 204 |
{ |
237 | 205 |
|
238 | 206 |
IVShmemState *s = opaque; |
... | ... | |
265 | 233 |
return ret; |
266 | 234 |
} |
267 | 235 |
|
268 |
static uint32_t ivshmem_io_readb(void *opaque, target_phys_addr_t addr) |
|
269 |
{ |
|
270 |
IVSHMEM_DPRINTF("We shouldn't be reading bytes\n"); |
|
271 |
|
|
272 |
return 0; |
|
273 |
} |
|
274 |
|
|
275 |
static CPUReadMemoryFunc * const ivshmem_mmio_read[3] = { |
|
276 |
ivshmem_io_readb, |
|
277 |
ivshmem_io_readw, |
|
278 |
ivshmem_io_readl, |
|
279 |
}; |
|
280 |
|
|
281 |
static CPUWriteMemoryFunc * const ivshmem_mmio_write[3] = { |
|
282 |
ivshmem_io_writeb, |
|
283 |
ivshmem_io_writew, |
|
284 |
ivshmem_io_writel, |
|
236 |
static const MemoryRegionOps ivshmem_mmio_ops = { |
|
237 |
.read = ivshmem_io_read, |
|
238 |
.write = ivshmem_io_write, |
|
239 |
.endianness = DEVICE_NATIVE_ENDIAN, |
|
240 |
.impl = { |
|
241 |
.min_access_size = 4, |
|
242 |
.max_access_size = 4, |
|
243 |
}, |
|
285 | 244 |
}; |
286 | 245 |
|
287 | 246 |
static void ivshmem_receive(void *opaque, const uint8_t *buf, int size) |
... | ... | |
371 | 330 |
|
372 | 331 |
ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); |
373 | 332 |
|
374 |
s->ivshmem_offset = qemu_ram_alloc_from_ptr(&s->dev.qdev, "ivshmem.bar2", |
|
375 |
s->ivshmem_size, ptr); |
|
333 |
memory_region_init_ram_ptr(&s->ivshmem, &s->dev.qdev, "ivshmem.bar2", |
|
334 |
s->ivshmem_size, ptr); |
|
335 |
memory_region_add_subregion(&s->bar, 0, &s->ivshmem); |
|
376 | 336 |
|
377 | 337 |
/* region for shared memory */ |
378 |
pci_register_bar(&s->dev, 2, s->ivshmem_size, |
|
379 |
PCI_BASE_ADDRESS_SPACE_MEMORY, ivshmem_map); |
|
338 |
pci_register_bar_region(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar); |
|
380 | 339 |
} |
381 | 340 |
|
382 | 341 |
static void close_guest_eventfds(IVShmemState *s, int posn) |
... | ... | |
401 | 360 |
|
402 | 361 |
for (i = 0; i <= s->max_peer; i++) { |
403 | 362 |
for (j = 0; j < s->peers[i].nb_eventfds; j++) { |
404 |
kvm_set_ioeventfd_mmio_long(s->peers[i].eventfds[j], |
|
405 |
s->mmio_addr + DOORBELL, (i << 16) | j, 1); |
|
363 |
memory_region_add_eventfd(&s->ivshmem_mmio, |
|
364 |
DOORBELL, |
|
365 |
4, |
|
366 |
true, |
|
367 |
(i << 16) | j, |
|
368 |
s->peers[i].eventfds[j]); |
|
406 | 369 |
} |
407 | 370 |
} |
408 | 371 |
} |
... | ... | |
483 | 446 |
/* mmap the region and map into the BAR2 */ |
484 | 447 |
map_ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, |
485 | 448 |
incoming_fd, 0); |
486 |
s->ivshmem_offset = qemu_ram_alloc_from_ptr(&s->dev.qdev,
|
|
487 |
"ivshmem.bar2", s->ivshmem_size, map_ptr);
|
|
449 |
memory_region_init_ram_ptr(&s->ivshmem, &s->dev.qdev,
|
|
450 |
"ivshmem.bar2", s->ivshmem_size, map_ptr); |
|
488 | 451 |
|
489 |
IVSHMEM_DPRINTF("guest pci addr = %" FMT_PCIBUS ", guest h/w addr = %" |
|
490 |
PRIu64 ", size = %" PRIu64 "\n", s->shm_pci_addr, |
|
452 |
IVSHMEM_DPRINTF("guest h/w addr = %" PRIu64 ", size = %" PRIu64 "\n", |
|
491 | 453 |
s->ivshmem_offset, s->ivshmem_size); |
492 | 454 |
|
493 |
if (s->shm_pci_addr > 0) { |
|
494 |
/* map memory into BAR2 */ |
|
495 |
cpu_register_physical_memory(s->shm_pci_addr, s->ivshmem_size, |
|
496 |
s->ivshmem_offset); |
|
497 |
} |
|
455 |
memory_region_add_subregion(&s->bar, 0, &s->ivshmem); |
|
498 | 456 |
|
499 | 457 |
/* only store the fd if it is successfully mapped */ |
500 | 458 |
s->shm_fd = incoming_fd; |
... | ... | |
549 | 507 |
return; |
550 | 508 |
} |
551 | 509 |
|
552 |
static void ivshmem_mmio_map(PCIDevice *pci_dev, int region_num, |
|
553 |
pcibus_t addr, pcibus_t size, int type) |
|
554 |
{ |
|
555 |
IVShmemState *s = DO_UPCAST(IVShmemState, dev, pci_dev); |
|
556 |
|
|
557 |
s->mmio_addr = addr; |
|
558 |
cpu_register_physical_memory(addr + 0, IVSHMEM_REG_BAR_SIZE, |
|
559 |
s->ivshmem_mmio_io_addr); |
|
560 |
|
|
561 |
if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) { |
|
562 |
setup_ioeventfds(s); |
|
563 |
} |
|
564 |
} |
|
565 |
|
|
566 | 510 |
static uint64_t ivshmem_get_size(IVShmemState * s) { |
567 | 511 |
|
568 | 512 |
uint64_t value; |
... | ... | |
710 | 654 |
|
711 | 655 |
pci_config_set_interrupt_pin(pci_conf, 1); |
712 | 656 |
|
713 |
s->shm_pci_addr = 0; |
|
714 |
s->ivshmem_offset = 0; |
|
715 | 657 |
s->shm_fd = 0; |
716 | 658 |
|
717 |
s->ivshmem_mmio_io_addr = cpu_register_io_memory(ivshmem_mmio_read, |
|
718 |
ivshmem_mmio_write, s, DEVICE_NATIVE_ENDIAN); |
|
659 |
memory_region_init_io(&s->ivshmem_mmio, &ivshmem_mmio_ops, s, |
|
660 |
"ivshmem-mmio", IVSHMEM_REG_BAR_SIZE); |
|
661 |
|
|
662 |
if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) { |
|
663 |
setup_ioeventfds(s); |
|
664 |
} |
|
665 |
|
|
719 | 666 |
/* region for registers*/ |
720 |
pci_register_bar(&s->dev, 0, IVSHMEM_REG_BAR_SIZE, |
|
721 |
PCI_BASE_ADDRESS_SPACE_MEMORY, ivshmem_mmio_map); |
|
667 |
pci_register_bar_region(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, |
|
668 |
&s->ivshmem_mmio); |
|
669 |
|
|
670 |
memory_region_init(&s->bar, "ivshmem-bar2-container", s->ivshmem_size); |
|
722 | 671 |
|
723 | 672 |
if ((s->server_chr != NULL) && |
724 | 673 |
(strncmp(s->server_chr->filename, "unix:", 5) == 0)) { |
... | ... | |
744 | 693 |
/* allocate/initialize space for interrupt handling */ |
745 | 694 |
s->peers = qemu_mallocz(s->nb_peers * sizeof(Peer)); |
746 | 695 |
|
747 |
pci_register_bar(&s->dev, 2, s->ivshmem_size,
|
|
748 |
PCI_BASE_ADDRESS_SPACE_MEMORY, ivshmem_map);
|
|
696 |
pci_register_bar_region(&s->dev, 2,
|
|
697 |
PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ivshmem);
|
|
749 | 698 |
|
750 | 699 |
s->eventfd_chr = qemu_mallocz(s->vectors * sizeof(CharDriverState *)); |
751 | 700 |
|
... | ... | |
792 | 741 |
{ |
793 | 742 |
IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev); |
794 | 743 |
|
795 |
cpu_unregister_io_memory(s->ivshmem_mmio_io_addr); |
|
744 |
memory_region_destroy(&s->ivshmem_mmio); |
|
745 |
memory_region_del_subregion(&s->bar, &s->ivshmem); |
|
746 |
memory_region_destroy(&s->ivshmem); |
|
747 |
memory_region_destroy(&s->bar); |
|
796 | 748 |
unregister_savevm(&dev->qdev, "ivshmem", s); |
797 | 749 |
|
798 | 750 |
return 0; |
Also available in: Unified diff