From: "Dr. David Alan Gilbert" <dgilb...@redhat.com> Add a cache BAR into which files will be directly mapped. The size can be set with the cache-size= property, e.g. -device vhost-user-fs-pci,chardev=char0,tag=myfs,cache-size=16G
The default is no cache. Signed-off-by: Dr. David Alan Gilbert <dgilb...@redhat.com> with PPC fixes by: Signed-off-by: Fabiano Rosas <faro...@linux.ibm.com> --- hw/virtio/vhost-user-fs-pci.c | 32 +++++++++++++++++++++++++++++++ hw/virtio/vhost-user-fs.c | 32 +++++++++++++++++++++++++++++++ include/hw/virtio/vhost-user-fs.h | 2 ++ 3 files changed, 66 insertions(+) diff --git a/hw/virtio/vhost-user-fs-pci.c b/hw/virtio/vhost-user-fs-pci.c index 2ed8492b3f..20e447631f 100644 --- a/hw/virtio/vhost-user-fs-pci.c +++ b/hw/virtio/vhost-user-fs-pci.c @@ -12,14 +12,19 @@ */ #include "qemu/osdep.h" +#include "qapi/error.h" #include "hw/qdev-properties.h" #include "hw/virtio/vhost-user-fs.h" #include "virtio-pci.h" #include "qom/object.h" +#include "standard-headers/linux/virtio_fs.h" + +#define VIRTIO_FS_PCI_CACHE_BAR 2 struct VHostUserFSPCI { VirtIOPCIProxy parent_obj; VHostUserFS vdev; + MemoryRegion cachebar; }; typedef struct VHostUserFSPCI VHostUserFSPCI; @@ -38,7 +43,9 @@ static Property vhost_user_fs_pci_properties[] = { static void vhost_user_fs_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) { VHostUserFSPCI *dev = VHOST_USER_FS_PCI(vpci_dev); + bool modern_pio = vpci_dev->flags & VIRTIO_PCI_FLAG_MODERN_PIO_NOTIFY; DeviceState *vdev = DEVICE(&dev->vdev); + uint64_t cachesize; if (vpci_dev->nvectors == DEV_NVECTORS_UNSPECIFIED) { /* Also reserve config change and hiprio queue vectors */ @@ -46,6 +53,31 @@ static void vhost_user_fs_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) } qdev_realize(vdev, BUS(&vpci_dev->bus), errp); + cachesize = dev->vdev.conf.cache_size; + + if (cachesize && modern_pio) { + error_setg(errp, "DAX Cache can not be used together with modern_pio"); + return; + } + + /* + * The bar starts with the data/DAX cache + * Others will be added later. + */ + memory_region_init(&dev->cachebar, OBJECT(vpci_dev), + "vhost-user-fs-pci-cachebar", cachesize); + if (cachesize) { + memory_region_add_subregion(&dev->cachebar, 0, &dev->vdev.cache); + virtio_pci_add_shm_cap(vpci_dev, VIRTIO_FS_PCI_CACHE_BAR, 0, cachesize, + VIRTIO_FS_SHMCAP_ID_CACHE); + + /* After 'realized' so the memory region exists */ + pci_register_bar(&vpci_dev->pci_dev, VIRTIO_FS_PCI_CACHE_BAR, + PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_PREFETCH | + PCI_BASE_ADDRESS_MEM_TYPE_64, + &dev->cachebar); + } } static void vhost_user_fs_pci_class_init(ObjectClass *klass, void *data) diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c index 6f7f91533d..dd0a02aa99 100644 --- a/hw/virtio/vhost-user-fs.c +++ b/hw/virtio/vhost-user-fs.c @@ -35,6 +35,16 @@ static const int user_feature_bits[] = { VHOST_INVALID_FEATURE_BIT }; +/* + * The powerpc kernel code expects the memory to be accessible during + * addition/removal. + */ +#if defined(TARGET_PPC64) && defined(CONFIG_LINUX) +#define DAX_WINDOW_PROT PROT_READ +#else +#define DAX_WINDOW_PROT PROT_NONE +#endif + static void vuf_get_config(VirtIODevice *vdev, uint8_t *config) { VHostUserFS *fs = VHOST_USER_FS(vdev); @@ -175,6 +185,7 @@ static void vuf_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VHostUserFS *fs = VHOST_USER_FS(dev); + void *cache_ptr; unsigned int i; size_t len; int ret; @@ -214,6 +225,26 @@ static void vuf_device_realize(DeviceState *dev, Error **errp) VIRTQUEUE_MAX_SIZE); return; } + if (fs->conf.cache_size && + (!is_power_of_2(fs->conf.cache_size) || + fs->conf.cache_size < qemu_real_host_page_size)) { + error_setg(errp, "cache-size property must be a power of 2 " + "no smaller than the page size"); + return; + } + if (fs->conf.cache_size) { + /* Anonymous, private memory is not counted as overcommit */ + cache_ptr = mmap(NULL, fs->conf.cache_size, DAX_WINDOW_PROT, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (cache_ptr == MAP_FAILED) { + error_setg(errp, "Unable to mmap blank cache"); + return; + } + + memory_region_init_ram_ptr(&fs->cache, OBJECT(vdev), + "virtio-fs-cache", + fs->conf.cache_size, cache_ptr); + } if (!vhost_user_init(&fs->vhost_user, &fs->conf.chardev, errp)) { return; @@ -289,6 +320,7 @@ static Property vuf_properties[] = { DEFINE_PROP_UINT16("num-request-queues", VHostUserFS, conf.num_request_queues, 1), DEFINE_PROP_UINT16("queue-size", VHostUserFS, conf.queue_size, 128), + DEFINE_PROP_SIZE("cache-size", VHostUserFS, conf.cache_size, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/virtio/vhost-user-fs.h b/include/hw/virtio/vhost-user-fs.h index 0d62834c25..04596799e3 100644 --- a/include/hw/virtio/vhost-user-fs.h +++ b/include/hw/virtio/vhost-user-fs.h @@ -28,6 +28,7 @@ typedef struct { char *tag; uint16_t num_request_queues; uint16_t queue_size; + uint64_t cache_size; } VHostUserFSConf; struct VHostUserFS { @@ -42,6 +43,7 @@ struct VHostUserFS { int32_t bootindex; /*< public >*/ + MemoryRegion cache; }; #endif /* _QEMU_VHOST_USER_FS_H */ -- 2.31.1