mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/stefanha-gitlab/tags/block-pull-request' into staging
Pull request for 5.2 NVMe fixes to solve IOMMU issues on non-x86 and error message/tracing improvements. Elena Afanasova's ioeventfd fixes are also included. Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> # gpg: Signature made Wed 04 Nov 2020 15:18:16 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: (33 commits) util/vfio-helpers: Assert offset is aligned to page size util/vfio-helpers: Convert vfio_dump_mapping to trace events util/vfio-helpers: Improve DMA trace events util/vfio-helpers: Trace where BARs are mapped util/vfio-helpers: Trace PCI BAR region info util/vfio-helpers: Trace PCI I/O config accesses util/vfio-helpers: Improve reporting unsupported IOMMU type block/nvme: Fix nvme_submit_command() on big-endian host block/nvme: Fix use of write-only doorbells page on Aarch64 arch block/nvme: Align iov's va and size on host page size block/nvme: Change size and alignment of prp_list_pages block/nvme: Change size and alignment of queue block/nvme: Change size and alignment of IDENTIFY response buffer block/nvme: Correct minimum device page size block/nvme: Set request_alignment at initialization block/nvme: Simplify nvme_cmd_sync() block/nvme: Simplify ADMIN queue access block/nvme: Correctly initialize Admin Queue Attributes block/nvme: Use definitions instead of magic values in add_io_queue() block/nvme: Introduce Completion Queue definitions ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -1882,6 +1882,7 @@ M: Klaus Jensen <its@irrelevant.dk>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: hw/block/nvme*
|
||||
F: include/block/nvme.h
|
||||
F: tests/qtest/nvme-test.c
|
||||
F: docs/specs/nvme.txt
|
||||
T: git git://git.infradead.org/qemu-nvme.git nvme-next
|
||||
@@ -2972,6 +2973,7 @@ R: Fam Zheng <fam@euphon.net>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: block/nvme*
|
||||
F: include/block/nvme.h
|
||||
T: git https://github.com/stefanha/qemu.git block
|
||||
|
||||
Bootdevice
|
||||
|
||||
+4
-2
@@ -2239,8 +2239,10 @@ static int kvm_init(MachineState *ms)
|
||||
|
||||
kvm_memory_listener_register(s, &s->memory_listener,
|
||||
&address_space_memory, 0);
|
||||
memory_listener_register(&kvm_io_listener,
|
||||
&address_space_io);
|
||||
if (kvm_eventfds_allowed) {
|
||||
memory_listener_register(&kvm_io_listener,
|
||||
&address_space_io);
|
||||
}
|
||||
memory_listener_register(&kvm_coalesced_pio_listener,
|
||||
&address_space_io);
|
||||
|
||||
|
||||
+117
-92
File diff suppressed because it is too large
Load Diff
+17
-13
@@ -134,25 +134,29 @@ qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t
|
||||
qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu"
|
||||
|
||||
# nvme.c
|
||||
nvme_kick(void *s, int queue) "s %p queue %d"
|
||||
nvme_controller_capability_raw(uint64_t value) "0x%08"PRIx64
|
||||
nvme_controller_capability(const char *desc, uint64_t value) "%s: %"PRIu64
|
||||
nvme_kick(void *s, unsigned q_index) "s %p q #%u"
|
||||
nvme_dma_flush_queue_wait(void *s) "s %p"
|
||||
nvme_error(int cmd_specific, int sq_head, int sqid, int cid, int status) "cmd_specific %d sq_head %d sqid %d cid %d status 0x%x"
|
||||
nvme_process_completion(void *s, int index, int inflight) "s %p queue %d inflight %d"
|
||||
nvme_process_completion_queue_plugged(void *s, int index) "s %p queue %d"
|
||||
nvme_complete_command(void *s, int index, int cid) "s %p queue %d cid %d"
|
||||
nvme_submit_command(void *s, int index, int cid) "s %p queue %d cid %d"
|
||||
nvme_process_completion(void *s, unsigned q_index, int inflight) "s %p q #%u inflight %d"
|
||||
nvme_process_completion_queue_plugged(void *s, unsigned q_index) "s %p q #%u"
|
||||
nvme_complete_command(void *s, unsigned q_index, int cid) "s %p q #%u cid %d"
|
||||
nvme_submit_command(void *s, unsigned q_index, int cid) "s %p q #%u cid %d"
|
||||
nvme_submit_command_raw(int c0, int c1, int c2, int c3, int c4, int c5, int c6, int c7) "%02x %02x %02x %02x %02x %02x %02x %02x"
|
||||
nvme_handle_event(void *s) "s %p"
|
||||
nvme_poll_cb(void *s) "s %p"
|
||||
nvme_prw_aligned(void *s, int is_write, uint64_t offset, uint64_t bytes, int flags, int niov) "s %p is_write %d offset %"PRId64" bytes %"PRId64" flags %d niov %d"
|
||||
nvme_write_zeroes(void *s, uint64_t offset, uint64_t bytes, int flags) "s %p offset %"PRId64" bytes %"PRId64" flags %d"
|
||||
nvme_poll_queue(void *s, unsigned q_index) "s %p q #%u"
|
||||
nvme_prw_aligned(void *s, int is_write, uint64_t offset, uint64_t bytes, int flags, int niov) "s %p is_write %d offset 0x%"PRIx64" bytes %"PRId64" flags %d niov %d"
|
||||
nvme_write_zeroes(void *s, uint64_t offset, uint64_t bytes, int flags) "s %p offset 0x%"PRIx64" bytes %"PRId64" flags %d"
|
||||
nvme_qiov_unaligned(const void *qiov, int n, void *base, size_t size, int align) "qiov %p n %d base %p size 0x%zx align 0x%x"
|
||||
nvme_prw_buffered(void *s, uint64_t offset, uint64_t bytes, int niov, int is_write) "s %p offset %"PRId64" bytes %"PRId64" niov %d is_write %d"
|
||||
nvme_rw_done(void *s, int is_write, uint64_t offset, uint64_t bytes, int ret) "s %p is_write %d offset %"PRId64" bytes %"PRId64" ret %d"
|
||||
nvme_dsm(void *s, uint64_t offset, uint64_t bytes) "s %p offset %"PRId64" bytes %"PRId64""
|
||||
nvme_dsm_done(void *s, uint64_t offset, uint64_t bytes, int ret) "s %p offset %"PRId64" bytes %"PRId64" ret %d"
|
||||
nvme_prw_buffered(void *s, uint64_t offset, uint64_t bytes, int niov, int is_write) "s %p offset 0x%"PRIx64" bytes %"PRId64" niov %d is_write %d"
|
||||
nvme_rw_done(void *s, int is_write, uint64_t offset, uint64_t bytes, int ret) "s %p is_write %d offset 0x%"PRIx64" bytes %"PRId64" ret %d"
|
||||
nvme_dsm(void *s, uint64_t offset, uint64_t bytes) "s %p offset 0x%"PRIx64" bytes %"PRId64""
|
||||
nvme_dsm_done(void *s, uint64_t offset, uint64_t bytes, int ret) "s %p offset 0x%"PRIx64" bytes %"PRId64" ret %d"
|
||||
nvme_dma_map_flush(void *s) "s %p"
|
||||
nvme_free_req_queue_wait(void *q) "q %p"
|
||||
nvme_free_req_queue_wait(void *s, unsigned q_index) "s %p q #%u"
|
||||
nvme_create_queue_pair(unsigned q_index, void *q, unsigned size, void *aio_context, int fd) "index %u q %p size %u aioctx %p fd %d"
|
||||
nvme_free_queue_pair(unsigned q_index, void *q) "index %u q %p"
|
||||
nvme_cmd_map_qiov(void *s, void *cmd, void *req, void *qiov, int entries) "s %p cmd %p req %p qiov %p entries %d"
|
||||
nvme_cmd_map_qiov_pages(void *s, int i, uint64_t page) "s %p page[%d] 0x%"PRIx64
|
||||
nvme_cmd_map_qiov_iov(void *s, int i, void *page, int pages) "s %p iov[%d] %p pages %d"
|
||||
|
||||
+12
-6
@@ -501,6 +501,11 @@ typedef struct QEMU_PACKED NvmeCreateCq {
|
||||
#define NVME_CQ_FLAGS_PC(cq_flags) (cq_flags & 0x1)
|
||||
#define NVME_CQ_FLAGS_IEN(cq_flags) ((cq_flags >> 1) & 0x1)
|
||||
|
||||
enum NvmeFlagsCq {
|
||||
NVME_CQ_PC = 1,
|
||||
NVME_CQ_IEN = 2,
|
||||
};
|
||||
|
||||
typedef struct QEMU_PACKED NvmeCreateSq {
|
||||
uint8_t opcode;
|
||||
uint8_t flags;
|
||||
@@ -518,12 +523,13 @@ typedef struct QEMU_PACKED NvmeCreateSq {
|
||||
#define NVME_SQ_FLAGS_PC(sq_flags) (sq_flags & 0x1)
|
||||
#define NVME_SQ_FLAGS_QPRIO(sq_flags) ((sq_flags >> 1) & 0x3)
|
||||
|
||||
enum NvmeQueueFlags {
|
||||
NVME_Q_PC = 1,
|
||||
NVME_Q_PRIO_URGENT = 0,
|
||||
NVME_Q_PRIO_HIGH = 1,
|
||||
NVME_Q_PRIO_NORMAL = 2,
|
||||
NVME_Q_PRIO_LOW = 3,
|
||||
enum NvmeFlagsSq {
|
||||
NVME_SQ_PC = 1,
|
||||
|
||||
NVME_SQ_PRIO_URGENT = 0,
|
||||
NVME_SQ_PRIO_HIGH = 1,
|
||||
NVME_SQ_PRIO_NORMAL = 2,
|
||||
NVME_SQ_PRIO_LOW = 3,
|
||||
};
|
||||
|
||||
typedef struct QEMU_PACKED NvmeIdentify {
|
||||
|
||||
+9
-2
@@ -205,8 +205,15 @@ static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd *a,
|
||||
static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd *a,
|
||||
MemoryRegionIoeventfd *b)
|
||||
{
|
||||
return !memory_region_ioeventfd_before(a, b)
|
||||
&& !memory_region_ioeventfd_before(b, a);
|
||||
if (int128_eq(a->addr.start, b->addr.start) &&
|
||||
(!int128_nz(a->addr.size) || !int128_nz(b->addr.size) ||
|
||||
(int128_eq(a->addr.size, b->addr.size) &&
|
||||
(a->match_data == b->match_data) &&
|
||||
((a->match_data && (a->data == b->data)) || !a->match_data) &&
|
||||
(a->e == b->e))))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Range of memory in the global map. Addresses are absolute. */
|
||||
|
||||
+8
-2
@@ -80,8 +80,14 @@ qemu_mutex_unlock(void *mutex, const char *file, const int line) "released mutex
|
||||
qemu_vfio_dma_reset_temporary(void *s) "s %p"
|
||||
qemu_vfio_ram_block_added(void *s, void *p, size_t size) "s %p host %p size 0x%zx"
|
||||
qemu_vfio_ram_block_removed(void *s, void *p, size_t size) "s %p host %p size 0x%zx"
|
||||
qemu_vfio_dump_mapping(void *host, uint64_t iova, size_t size) "vfio mapping %p to iova 0x%08" PRIx64 " size 0x%zx"
|
||||
qemu_vfio_find_mapping(void *s, void *p) "s %p host %p"
|
||||
qemu_vfio_new_mapping(void *s, void *host, size_t size, int index, uint64_t iova) "s %p host %p size 0x%zx index %d iova 0x%"PRIx64
|
||||
qemu_vfio_do_mapping(void *s, void *host, size_t size, uint64_t iova) "s %p host %p size 0x%zx iova 0x%"PRIx64
|
||||
qemu_vfio_dma_map(void *s, void *host, size_t size, bool temporary, uint64_t *iova) "s %p host %p size 0x%zx temporary %d iova %p"
|
||||
qemu_vfio_do_mapping(void *s, void *host, uint64_t iova, size_t size) "s %p host %p <-> iova 0x%"PRIx64 " size 0x%zx"
|
||||
qemu_vfio_dma_map(void *s, void *host, size_t size, bool temporary, uint64_t *iova) "s %p host %p size 0x%zx temporary %d &iova %p"
|
||||
qemu_vfio_dma_mapped(void *s, void *host, uint64_t iova, size_t size) "s %p host %p <-> iova 0x%"PRIx64" size 0x%zx"
|
||||
qemu_vfio_dma_unmap(void *s, void *host) "s %p host %p"
|
||||
qemu_vfio_pci_read_config(void *buf, int ofs, int size, uint64_t region_ofs, uint64_t region_size) "read cfg ptr %p ofs 0x%x size 0x%x (region addr 0x%"PRIx64" size 0x%"PRIx64")"
|
||||
qemu_vfio_pci_write_config(void *buf, int ofs, int size, uint64_t region_ofs, uint64_t region_size) "write cfg ptr %p ofs 0x%x size 0x%x (region addr 0x%"PRIx64" size 0x%"PRIx64")"
|
||||
qemu_vfio_region_info(const char *desc, uint64_t region_ofs, uint64_t region_size, uint32_t cap_offset) "region '%s' addr 0x%"PRIx64" size 0x%"PRIx64" cap_ofs 0x%"PRIx32
|
||||
qemu_vfio_pci_map_bar(int index, uint64_t region_ofs, uint64_t region_size, int ofs, void *host) "map region bar#%d addr 0x%"PRIx64" size 0x%"PRIx64" ofs 0x%x host %p"
|
||||
|
||||
+26
-17
@@ -137,6 +137,7 @@ static inline void assert_bar_index_valid(QEMUVFIOState *s, int index)
|
||||
|
||||
static int qemu_vfio_pci_init_bar(QEMUVFIOState *s, int index, Error **errp)
|
||||
{
|
||||
g_autofree char *barname = NULL;
|
||||
assert_bar_index_valid(s, index);
|
||||
s->bar_region_info[index] = (struct vfio_region_info) {
|
||||
.index = VFIO_PCI_BAR0_REGION_INDEX + index,
|
||||
@@ -146,6 +147,10 @@ static int qemu_vfio_pci_init_bar(QEMUVFIOState *s, int index, Error **errp)
|
||||
error_setg_errno(errp, errno, "Failed to get BAR region info");
|
||||
return -errno;
|
||||
}
|
||||
barname = g_strdup_printf("bar[%d]", index);
|
||||
trace_qemu_vfio_region_info(barname, s->bar_region_info[index].offset,
|
||||
s->bar_region_info[index].size,
|
||||
s->bar_region_info[index].cap_offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -158,10 +163,13 @@ void *qemu_vfio_pci_map_bar(QEMUVFIOState *s, int index,
|
||||
Error **errp)
|
||||
{
|
||||
void *p;
|
||||
assert(QEMU_IS_ALIGNED(offset, qemu_real_host_page_size));
|
||||
assert_bar_index_valid(s, index);
|
||||
p = mmap(NULL, MIN(size, s->bar_region_info[index].size - offset),
|
||||
prot, MAP_SHARED,
|
||||
s->device, s->bar_region_info[index].offset + offset);
|
||||
trace_qemu_vfio_pci_map_bar(index, s->bar_region_info[index].offset ,
|
||||
size, offset, p);
|
||||
if (p == MAP_FAILED) {
|
||||
error_setg_errno(errp, errno, "Failed to map BAR region");
|
||||
p = NULL;
|
||||
@@ -228,6 +236,10 @@ static int qemu_vfio_pci_read_config(QEMUVFIOState *s, void *buf,
|
||||
{
|
||||
int ret;
|
||||
|
||||
trace_qemu_vfio_pci_read_config(buf, ofs, size,
|
||||
s->config_region_info.offset,
|
||||
s->config_region_info.size);
|
||||
assert(QEMU_IS_ALIGNED(s->config_region_info.offset + ofs, size));
|
||||
do {
|
||||
ret = pread(s->device, buf, size, s->config_region_info.offset + ofs);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
@@ -238,6 +250,10 @@ static int qemu_vfio_pci_write_config(QEMUVFIOState *s, void *buf, int size, int
|
||||
{
|
||||
int ret;
|
||||
|
||||
trace_qemu_vfio_pci_write_config(buf, ofs, size,
|
||||
s->config_region_info.offset,
|
||||
s->config_region_info.size);
|
||||
assert(QEMU_IS_ALIGNED(s->config_region_info.offset + ofs, size));
|
||||
do {
|
||||
ret = pwrite(s->device, buf, size, s->config_region_info.offset + ofs);
|
||||
} while (ret == -1 && errno == EINTR);
|
||||
@@ -301,7 +317,7 @@ static int qemu_vfio_init_pci(QEMUVFIOState *s, const char *device,
|
||||
}
|
||||
|
||||
if (!ioctl(s->container, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU)) {
|
||||
error_setg_errno(errp, errno, "VFIO IOMMU check failed");
|
||||
error_setg_errno(errp, errno, "VFIO IOMMU Type1 is not supported");
|
||||
ret = -EINVAL;
|
||||
goto fail_container;
|
||||
}
|
||||
@@ -409,6 +425,9 @@ static int qemu_vfio_init_pci(QEMUVFIOState *s, const char *device,
|
||||
ret = -errno;
|
||||
goto fail;
|
||||
}
|
||||
trace_qemu_vfio_region_info("config", s->config_region_info.offset,
|
||||
s->config_region_info.size,
|
||||
s->config_region_info.cap_offset);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(s->bar_region_info); i++) {
|
||||
ret = qemu_vfio_pci_init_bar(s, i, errp);
|
||||
@@ -516,23 +535,12 @@ QEMUVFIOState *qemu_vfio_open_pci(const char *device, Error **errp)
|
||||
return s;
|
||||
}
|
||||
|
||||
static void qemu_vfio_dump_mapping(IOVAMapping *m)
|
||||
{
|
||||
if (QEMU_VFIO_DEBUG) {
|
||||
printf(" vfio mapping %p %" PRIx64 " to %" PRIx64 "\n", m->host,
|
||||
(uint64_t)m->size, (uint64_t)m->iova);
|
||||
}
|
||||
}
|
||||
|
||||
static void qemu_vfio_dump_mappings(QEMUVFIOState *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (QEMU_VFIO_DEBUG) {
|
||||
printf("vfio mappings\n");
|
||||
for (i = 0; i < s->nr_mappings; ++i) {
|
||||
qemu_vfio_dump_mapping(&s->mappings[i]);
|
||||
}
|
||||
for (int i = 0; i < s->nr_mappings; ++i) {
|
||||
trace_qemu_vfio_dump_mapping(s->mappings[i].host,
|
||||
s->mappings[i].iova,
|
||||
s->mappings[i].size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,7 +630,7 @@ static int qemu_vfio_do_mapping(QEMUVFIOState *s, void *host, size_t size,
|
||||
.vaddr = (uintptr_t)host,
|
||||
.size = size,
|
||||
};
|
||||
trace_qemu_vfio_do_mapping(s, host, size, iova);
|
||||
trace_qemu_vfio_do_mapping(s, host, iova, size);
|
||||
|
||||
if (ioctl(s->container, VFIO_IOMMU_MAP_DMA, &dma_map)) {
|
||||
error_report("VFIO_MAP_DMA failed: %s", strerror(errno));
|
||||
@@ -778,6 +786,7 @@ int qemu_vfio_dma_map(QEMUVFIOState *s, void *host, size_t size,
|
||||
}
|
||||
}
|
||||
}
|
||||
trace_qemu_vfio_dma_mapped(s, host, iova0, size);
|
||||
if (iova) {
|
||||
*iova = iova0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user