diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-02-10 15:42:19 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-02-10 15:42:20 +0000 |
commit | 83339e21d05c824ebc9131d644f25c23d0e41ecf (patch) | |
tree | 3254c62fa674de5d3d3ae02743122ecccb000fe3 /include | |
parent | 7b2c4cdd794e499883281c18770b2d16adebfaac (diff) | |
parent | eb847c42296497978942f738cd41dc29a35a49b2 (diff) |
Merge remote-tracking branch 'remotes/stefanha-gitlab/tags/block-pull-request' into staging
Pull request
v4:
* Add PCI_EXPRESS Kconfig dependency to fix s390x in "multi-process: setup PCI
host bridge for remote device" [Philippe and Thomas]
# gpg: Signature made Wed 10 Feb 2021 09:26:14 GMT
# gpg: using RSA key 8695A8BFD3F97CDAAC35775A9CA4ABB381AB73C8
# gpg: Good signature from "Stefan Hajnoczi <stefanha@redhat.com>" [full]
# gpg: aka "Stefan Hajnoczi <stefanha@gmail.com>" [full]
# Primary key fingerprint: 8695 A8BF D3F9 7CDA AC35 775A 9CA4 ABB3 81AB 73C8
* remotes/stefanha-gitlab/tags/block-pull-request: (27 commits)
docs: fix Parallels Image "dirty bitmap" section
multi-process: perform device reset in the remote process
multi-process: Retrieve PCI info from remote process
multi-process: create IOHUB object to handle irq
multi-process: Synchronize remote memory
multi-process: PCI BAR read/write handling for proxy & remote endpoints
multi-process: Forward PCI config space acceses to the remote process
multi-process: add proxy communication functions
multi-process: introduce proxy object
multi-process: setup memory manager for remote device
multi-process: Associate fd of a PCIDevice with its object
multi-process: Initialize message handler in remote device
multi-process: define MPQemuMsg format and transmission functions
io: add qio_channel_readv_full_all_eof & qio_channel_readv_full_all helpers
io: add qio_channel_writev_full_all helper
multi-process: setup a machine object for remote device process
multi-process: setup PCI host bridge for remote device
multi-process: Add config option for multi-process QEMU
memory: alloc RAM from file at offset
multi-process: add configure and usage information
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/exec/memory.h | 2 | ||||
-rw-r--r-- | include/exec/ram_addr.h | 4 | ||||
-rw-r--r-- | include/hw/pci-host/remote.h | 30 | ||||
-rw-r--r-- | include/hw/pci/pci_ids.h | 3 | ||||
-rw-r--r-- | include/hw/remote/iohub.h | 42 | ||||
-rw-r--r-- | include/hw/remote/machine.h | 38 | ||||
-rw-r--r-- | include/hw/remote/memory.h | 19 | ||||
-rw-r--r-- | include/hw/remote/mpqemu-link.h | 99 | ||||
-rw-r--r-- | include/hw/remote/proxy-memory-listener.h | 28 | ||||
-rw-r--r-- | include/hw/remote/proxy.h | 48 | ||||
-rw-r--r-- | include/io/channel.h | 78 | ||||
-rw-r--r-- | include/qemu/mmap-alloc.h | 4 | ||||
-rw-r--r-- | include/sysemu/iothread.h | 6 |
13 files changed, 398 insertions, 3 deletions
diff --git a/include/exec/memory.h b/include/exec/memory.h index ed292767cd..c6fb714e49 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -998,6 +998,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, * @size: size of the region. * @share: %true if memory must be mmaped with the MAP_SHARED flag * @fd: the fd to mmap. + * @offset: offset within the file referenced by fd * @errp: pointer to Error*, to store an error if it happens. * * Note that this function does not do anything to cause the data in the @@ -1009,6 +1010,7 @@ void memory_region_init_ram_from_fd(MemoryRegion *mr, uint64_t size, bool share, int fd, + ram_addr_t offset, Error **errp); #endif diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 40b16609ab..3cb9791df3 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -121,8 +121,8 @@ RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, uint32_t ram_flags, const char *mem_path, bool readonly, Error **errp); RAMBlock *qemu_ram_alloc_from_fd(ram_addr_t size, MemoryRegion *mr, - uint32_t ram_flags, int fd, bool readonly, - Error **errp); + uint32_t ram_flags, int fd, off_t offset, + bool readonly, Error **errp); RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr, Error **errp); diff --git a/include/hw/pci-host/remote.h b/include/hw/pci-host/remote.h new file mode 100644 index 0000000000..3dcf6aa51d --- /dev/null +++ b/include/hw/pci-host/remote.h @@ -0,0 +1,30 @@ +/* + * PCI Host for remote device + * + * Copyright © 2018, 2021 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef REMOTE_PCIHOST_H +#define REMOTE_PCIHOST_H + +#include "exec/memory.h" +#include "hw/pci/pcie_host.h" + +#define TYPE_REMOTE_PCIHOST "remote-pcihost" +OBJECT_DECLARE_SIMPLE_TYPE(RemotePCIHost, REMOTE_PCIHOST) + +struct RemotePCIHost { + /*< private >*/ + PCIExpressHost parent_obj; + /*< public >*/ + + MemoryRegion *mr_pci_mem; + MemoryRegion *mr_sys_io; + MemoryRegion *mr_sys_mem; +}; + +#endif diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index 11f8ab7149..bd0c17dc78 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -192,6 +192,9 @@ #define PCI_DEVICE_ID_SUN_SIMBA 0x5000 #define PCI_DEVICE_ID_SUN_SABRE 0xa000 +#define PCI_VENDOR_ID_ORACLE 0x108e +#define PCI_DEVICE_ID_REMOTE_IOHUB 0xb000 + #define PCI_VENDOR_ID_CMD 0x1095 #define PCI_DEVICE_ID_CMD_646 0x0646 diff --git a/include/hw/remote/iohub.h b/include/hw/remote/iohub.h new file mode 100644 index 0000000000..0bf98e0d78 --- /dev/null +++ b/include/hw/remote/iohub.h @@ -0,0 +1,42 @@ +/* + * IO Hub for remote device + * + * Copyright © 2018, 2021 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef REMOTE_IOHUB_H +#define REMOTE_IOHUB_H + +#include "hw/pci/pci.h" +#include "qemu/event_notifier.h" +#include "qemu/thread-posix.h" +#include "hw/remote/mpqemu-link.h" + +#define REMOTE_IOHUB_NB_PIRQS PCI_DEVFN_MAX + +typedef struct ResampleToken { + void *iohub; + int pirq; +} ResampleToken; + +typedef struct RemoteIOHubState { + PCIDevice d; + EventNotifier irqfds[REMOTE_IOHUB_NB_PIRQS]; + EventNotifier resamplefds[REMOTE_IOHUB_NB_PIRQS]; + unsigned int irq_level[REMOTE_IOHUB_NB_PIRQS]; + ResampleToken token[REMOTE_IOHUB_NB_PIRQS]; + QemuMutex irq_level_lock[REMOTE_IOHUB_NB_PIRQS]; +} RemoteIOHubState; + +int remote_iohub_map_irq(PCIDevice *pci_dev, int intx); +void remote_iohub_set_irq(void *opaque, int pirq, int level); +void process_set_irqfd_msg(PCIDevice *pci_dev, MPQemuMsg *msg); + +void remote_iohub_init(RemoteIOHubState *iohub); +void remote_iohub_finalize(RemoteIOHubState *iohub); + +#endif diff --git a/include/hw/remote/machine.h b/include/hw/remote/machine.h new file mode 100644 index 0000000000..2a2a33c4b2 --- /dev/null +++ b/include/hw/remote/machine.h @@ -0,0 +1,38 @@ +/* + * Remote machine configuration + * + * Copyright © 2018, 2021 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef REMOTE_MACHINE_H +#define REMOTE_MACHINE_H + +#include "qom/object.h" +#include "hw/boards.h" +#include "hw/pci-host/remote.h" +#include "io/channel.h" +#include "hw/remote/iohub.h" + +struct RemoteMachineState { + MachineState parent_obj; + + RemotePCIHost *host; + RemoteIOHubState iohub; +}; + +/* Used to pass to co-routine device and ioc. */ +typedef struct RemoteCommDev { + PCIDevice *dev; + QIOChannel *ioc; +} RemoteCommDev; + +#define TYPE_REMOTE_MACHINE "x-remote-machine" +OBJECT_DECLARE_SIMPLE_TYPE(RemoteMachineState, REMOTE_MACHINE) + +void coroutine_fn mpqemu_remote_msg_loop_co(void *data); + +#endif diff --git a/include/hw/remote/memory.h b/include/hw/remote/memory.h new file mode 100644 index 0000000000..bc2e30945f --- /dev/null +++ b/include/hw/remote/memory.h @@ -0,0 +1,19 @@ +/* + * Memory manager for remote device + * + * Copyright © 2018, 2021 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef REMOTE_MEMORY_H +#define REMOTE_MEMORY_H + +#include "exec/hwaddr.h" +#include "hw/remote/mpqemu-link.h" + +void remote_sysmem_reconfig(MPQemuMsg *msg, Error **errp); + +#endif diff --git a/include/hw/remote/mpqemu-link.h b/include/hw/remote/mpqemu-link.h new file mode 100644 index 0000000000..4ec0915885 --- /dev/null +++ b/include/hw/remote/mpqemu-link.h @@ -0,0 +1,99 @@ +/* + * Communication channel between QEMU and remote device process + * + * Copyright © 2018, 2021 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef MPQEMU_LINK_H +#define MPQEMU_LINK_H + +#include "qom/object.h" +#include "qemu/thread.h" +#include "io/channel.h" +#include "exec/hwaddr.h" +#include "io/channel-socket.h" +#include "hw/remote/proxy.h" + +#define REMOTE_MAX_FDS 8 + +#define MPQEMU_MSG_HDR_SIZE offsetof(MPQemuMsg, data.u64) + +/** + * MPQemuCmd: + * + * MPQemuCmd enum type to specify the command to be executed on the remote + * device. + * + * This uses a private protocol between QEMU and the remote process. vfio-user + * protocol would supersede this in the future. + * + */ +typedef enum { + MPQEMU_CMD_SYNC_SYSMEM, + MPQEMU_CMD_RET, + MPQEMU_CMD_PCI_CFGWRITE, + MPQEMU_CMD_PCI_CFGREAD, + MPQEMU_CMD_BAR_WRITE, + MPQEMU_CMD_BAR_READ, + MPQEMU_CMD_SET_IRQFD, + MPQEMU_CMD_DEVICE_RESET, + MPQEMU_CMD_MAX, +} MPQemuCmd; + +typedef struct { + hwaddr gpas[REMOTE_MAX_FDS]; + uint64_t sizes[REMOTE_MAX_FDS]; + off_t offsets[REMOTE_MAX_FDS]; +} SyncSysmemMsg; + +typedef struct { + uint32_t addr; + uint32_t val; + int len; +} PciConfDataMsg; + +typedef struct { + hwaddr addr; + uint64_t val; + unsigned size; + bool memory; +} BarAccessMsg; + +/** + * MPQemuMsg: + * @cmd: The remote command + * @size: Size of the data to be shared + * @data: Structured data + * @fds: File descriptors to be shared with remote device + * + * MPQemuMsg Format of the message sent to the remote device from QEMU. + * + */ + +typedef struct { + int cmd; + size_t size; + + union { + uint64_t u64; + PciConfDataMsg pci_conf_data; + SyncSysmemMsg sync_sysmem; + BarAccessMsg bar_access; + } data; + + int fds[REMOTE_MAX_FDS]; + int num_fds; +} MPQemuMsg; + +bool mpqemu_msg_send(MPQemuMsg *msg, QIOChannel *ioc, Error **errp); +bool mpqemu_msg_recv(MPQemuMsg *msg, QIOChannel *ioc, Error **errp); + +uint64_t mpqemu_msg_send_and_await_reply(MPQemuMsg *msg, PCIProxyDev *pdev, + Error **errp); +bool mpqemu_msg_valid(MPQemuMsg *msg); + +#endif diff --git a/include/hw/remote/proxy-memory-listener.h b/include/hw/remote/proxy-memory-listener.h new file mode 100644 index 0000000000..c4f3efb928 --- /dev/null +++ b/include/hw/remote/proxy-memory-listener.h @@ -0,0 +1,28 @@ +/* + * Copyright © 2018, 2021 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef PROXY_MEMORY_LISTENER_H +#define PROXY_MEMORY_LISTENER_H + +#include "exec/memory.h" +#include "io/channel.h" + +typedef struct ProxyMemoryListener { + MemoryListener listener; + + int n_mr_sections; + MemoryRegionSection *mr_sections; + + QIOChannel *ioc; +} ProxyMemoryListener; + +void proxy_memory_listener_configure(ProxyMemoryListener *proxy_listener, + QIOChannel *ioc); +void proxy_memory_listener_deconfigure(ProxyMemoryListener *proxy_listener); + +#endif diff --git a/include/hw/remote/proxy.h b/include/hw/remote/proxy.h new file mode 100644 index 0000000000..741def71f1 --- /dev/null +++ b/include/hw/remote/proxy.h @@ -0,0 +1,48 @@ +/* + * Copyright © 2018, 2021 Oracle and/or its affiliates. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ + +#ifndef PROXY_H +#define PROXY_H + +#include "hw/pci/pci.h" +#include "io/channel.h" +#include "hw/remote/proxy-memory-listener.h" +#include "qemu/event_notifier.h" + +#define TYPE_PCI_PROXY_DEV "x-pci-proxy-dev" +OBJECT_DECLARE_SIMPLE_TYPE(PCIProxyDev, PCI_PROXY_DEV) + +typedef struct ProxyMemoryRegion { + PCIProxyDev *dev; + MemoryRegion mr; + bool memory; + bool present; + uint8_t type; +} ProxyMemoryRegion; + +struct PCIProxyDev { + PCIDevice parent_dev; + char *fd; + + /* + * Mutex used to protect the QIOChannel fd from + * the concurrent access by the VCPUs since proxy + * blocks while awaiting for the replies from the + * process remote. + */ + QemuMutex io_mutex; + QIOChannel *ioc; + Error *migration_blocker; + ProxyMemoryListener proxy_listener; + int virq; + EventNotifier intr; + EventNotifier resample; + ProxyMemoryRegion region[PCI_NUM_REGIONS]; +}; + +#endif /* PROXY_H */ diff --git a/include/io/channel.h b/include/io/channel.h index ab9ea77959..88988979f8 100644 --- a/include/io/channel.h +++ b/include/io/channel.h @@ -777,4 +777,82 @@ void qio_channel_set_aio_fd_handler(QIOChannel *ioc, IOHandler *io_write, void *opaque); +/** + * qio_channel_readv_full_all_eof: + * @ioc: the channel object + * @iov: the array of memory regions to read data to + * @niov: the length of the @iov array + * @fds: an array of file handles to read + * @nfds: number of file handles in @fds + * @errp: pointer to a NULL-initialized error object + * + * + * Performs same function as qio_channel_readv_all_eof. + * Additionally, attempts to read file descriptors shared + * over the channel. The function will wait for all + * requested data to be read, yielding from the current + * coroutine if required. data refers to both file + * descriptors and the iovs. + * + * Returns: 1 if all bytes were read, 0 if end-of-file + * occurs without data, or -1 on error + */ + +int qio_channel_readv_full_all_eof(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + int **fds, size_t *nfds, + Error **errp); + +/** + * qio_channel_readv_full_all: + * @ioc: the channel object + * @iov: the array of memory regions to read data to + * @niov: the length of the @iov array + * @fds: an array of file handles to read + * @nfds: number of file handles in @fds + * @errp: pointer to a NULL-initialized error object + * + * + * Performs same function as qio_channel_readv_all_eof. + * Additionally, attempts to read file descriptors shared + * over the channel. The function will wait for all + * requested data to be read, yielding from the current + * coroutine if required. data refers to both file + * descriptors and the iovs. + * + * Returns: 0 if all bytes were read, or -1 on error + */ + +int qio_channel_readv_full_all(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + int **fds, size_t *nfds, + Error **errp); + +/** + * qio_channel_writev_full_all: + * @ioc: the channel object + * @iov: the array of memory regions to write data from + * @niov: the length of the @iov array + * @fds: an array of file handles to send + * @nfds: number of file handles in @fds + * @errp: pointer to a NULL-initialized error object + * + * + * Behaves like qio_channel_writev_full but will attempt + * to send all data passed (file handles and memory regions). + * The function will wait for all requested data + * to be written, yielding from the current coroutine + * if required. + * + * Returns: 0 if all bytes were written, or -1 on error + */ + +int qio_channel_writev_full_all(QIOChannel *ioc, + const struct iovec *iov, + size_t niov, + int *fds, size_t nfds, + Error **errp); + #endif /* QIO_CHANNEL_H */ diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h index 8b7a5c70f3..456ff87df1 100644 --- a/include/qemu/mmap-alloc.h +++ b/include/qemu/mmap-alloc.h @@ -17,6 +17,7 @@ size_t qemu_mempath_getpagesize(const char *mem_path); * @readonly: true for a read-only mapping, false for read/write. * @shared: map has RAM_SHARED flag. * @is_pmem: map has RAM_PMEM flag. + * @map_offset: map starts at offset of map_offset from the start of fd * * Return: * On success, return a pointer to the mapped area. @@ -27,7 +28,8 @@ void *qemu_ram_mmap(int fd, size_t align, bool readonly, bool shared, - bool is_pmem); + bool is_pmem, + off_t map_offset); void qemu_ram_munmap(int fd, void *ptr, size_t size); diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h index 0c5284dbbc..f177142f16 100644 --- a/include/sysemu/iothread.h +++ b/include/sysemu/iothread.h @@ -57,4 +57,10 @@ IOThread *iothread_create(const char *id, Error **errp); void iothread_stop(IOThread *iothread); void iothread_destroy(IOThread *iothread); +/* + * Returns true if executing withing IOThread context, + * false otherwise. + */ +bool qemu_in_iothread(void); + #endif /* IOTHREAD_H */ |