From c9b72c7d35931c77818c5da420bb0761c1ba9f55 Mon Sep 17 00:00:00 2001 From: Levente Kurusa Date: Sun, 31 Aug 2014 11:53:55 +0200 Subject: [PATCH 1/4] ivshmem: add a register-only BAR Add two new registers: IRQSTATUS, to show the interrupt status without resetting it IVSHMVER, to make sure guests can differentiate between ivshmem versions ... and reserve the rest for the future. These registers are read-only at the moment. In the future, however, there might be a need for writeable registers as well. Current ivshmem version is 1, so guests which do not see BAR3 can use 0 internally. Signed-off-by: Levente Kurusa --- hw/misc/ivshmem.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index bd9d718..f6e626c 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -40,6 +40,9 @@ #define IVSHMEM_REG_BAR_SIZE 0x100 +/* Bump everytime you do user visible modifications */ +#define IVSHMEM_CURRENT_VERSION 1 + //#define DEBUG_IVSHMEM #ifdef DEBUG_IVSHMEM #define IVSHMEM_DPRINTF(fmt, ...) \ @@ -74,6 +77,7 @@ typedef struct IVShmemState { CharDriverState **eventfd_chr; CharDriverState *server_chr; MemoryRegion ivshmem_mmio; + MemoryRegion ivshmem_secondreg; /* We might need to register the BAR before we actually have the memory. * So prepare a container MemoryRegion for the BAR immediately and @@ -111,6 +115,13 @@ enum ivshmem_registers { DOORBELL = 12, }; +/* BAR3 registers act as secondary registers */ +enum ivshmem_secondary_registers { + IRQSTATUS = 0, + IVSHMVER = 4, + /* Rest is reserved */ +}; + static inline uint32_t ivshmem_has_feature(IVShmemState *ivs, unsigned int feature) { return (ivs->features & (1 << feature)); @@ -248,6 +259,25 @@ static uint64_t ivshmem_io_read(void *opaque, hwaddr addr, return ret; } +static uint64_t ivshmem_secondreg_read(void *opaque, hwaddr addr, + unsigned size) +{ + IVShmemState *s = opaque; + uint32_t ret = 0; + + switch(addr) + { + case IRQSTATUS: + ret = s->intrstatus; + break; + case IVSHMVER: + ret = IVSHMEM_CURRENT_VERSION; + break; + } + + return ret; +} + static const MemoryRegionOps ivshmem_mmio_ops = { .read = ivshmem_io_read, .write = ivshmem_io_write, @@ -258,6 +288,15 @@ static const MemoryRegionOps ivshmem_mmio_ops = { }, }; +static const MemoryRegionOps ivshmem_secondreg_ops = { + .read = ivshmem_secondreg_read, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 4, + .max_access_size = 4, + }, +}; + static void ivshmem_receive(void *opaque, const uint8_t *buf, int size) { IVShmemState *s = opaque; @@ -707,6 +746,13 @@ static int pci_ivshmem_init(PCIDevice *dev) pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ivshmem_mmio); + /* register secondary registers */ + memory_region_init_io(&s->ivshmem_secondreg, OBJECT(s), &ivshmem_secondreg_ops, s, + "ivshmem-secondreg", IVSHMEM_REG_BAR_SIZE); + + pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_MEMORY, + &s->ivshmem_secondreg); + memory_region_init(&s->bar, OBJECT(s), "ivshmem-bar2-container", s->ivshmem_size); s->ivshmem_attr = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_PREFETCH; -- 1.8.3.1