[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 13/29] xen/HVM: atomically access pointers in bufiore
From: |
Stefano Stabellini |
Subject: |
[Qemu-devel] [PULL 13/29] xen/HVM: atomically access pointers in bufioreq handling |
Date: |
Thu, 10 Sep 2015 18:15:45 +0100 |
From: Jan Beulich <address@hidden>
The number of slots per page being 511 (i.e. not a power of two) means
that the (32-bit) read and write indexes going beyond 2^32 will likely
disturb operation. The hypervisor side gets I/O req server creation
extended so we can indicate that we're using suitable atomic accesses
where needed, allowing it to atomically canonicalize both pointers when
both have gone through at least one cycle.
The Xen side counterpart (which is not a functional prereq to this
change, albeit a build one) went in already (commit b7007bc6f9).
Signed-off-by: Jan Beulich <address@hidden>
Signed-off-by: Stefano Stabellini <address@hidden>
---
configure | 27 +++++++++++++++++++++++++++
include/hw/xen/xen_common.h | 12 +++++++++++-
xen-hvm.c | 26 ++++++++++++++++++--------
3 files changed, 56 insertions(+), 9 deletions(-)
diff --git a/configure b/configure
index d854936..5618bf1 100755
--- a/configure
+++ b/configure
@@ -1889,6 +1889,33 @@ int main(void) {
xc_gnttab_open(NULL, 0);
xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0);
xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000);
+ xc_hvm_create_ioreq_server(xc, 0, HVM_IOREQSRV_BUFIOREQ_ATOMIC, NULL);
+ return 0;
+}
+EOF
+ compile_prog "" "$xen_libs"
+ then
+ xen_ctrl_version=460
+ xen=yes
+
+ # Xen 4.5
+ elif
+ cat > $TMPC <<EOF &&
+#include <xenctrl.h>
+#include <xenstore.h>
+#include <stdint.h>
+#include <xen/hvm/hvm_info_table.h>
+#if !defined(HVM_MAX_VCPUS)
+# error HVM_MAX_VCPUS not defined
+#endif
+int main(void) {
+ xc_interface *xc;
+ xs_daemon_open();
+ xc = xc_interface_open(0, 0, 0);
+ xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0);
+ xc_gnttab_open(NULL, 0);
+ xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0);
+ xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000);
xc_hvm_create_ioreq_server(xc, 0, 0, NULL);
return 0;
}
diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h
index ed5fd3e..19d0bca 100644
--- a/include/hw/xen/xen_common.h
+++ b/include/hw/xen/xen_common.h
@@ -186,6 +186,15 @@ static inline int xen_get_vmport_regs_pfn(XenXC xc,
domid_t dom,
}
#endif
+/* Xen before 4.6 */
+#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 460
+
+#ifndef HVM_IOREQSRV_BUFIOREQ_ATOMIC
+#define HVM_IOREQSRV_BUFIOREQ_ATOMIC 2
+#endif
+
+#endif
+
/* Xen before 4.5 */
#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 450
@@ -370,7 +379,8 @@ static inline void xen_unmap_pcidev(XenXC xc, domid_t dom,
static inline int xen_create_ioreq_server(XenXC xc, domid_t dom,
ioservid_t *ioservid)
{
- int rc = xc_hvm_create_ioreq_server(xc, dom, 1, ioservid);
+ int rc = xc_hvm_create_ioreq_server(xc, dom, HVM_IOREQSRV_BUFIOREQ_ATOMIC,
+ ioservid);
if (rc == 0) {
trace_xen_ioreq_server_create(*ioservid);
diff --git a/xen-hvm.c b/xen-hvm.c
index 0f81f7f..cbd0a79 100644
--- a/xen-hvm.c
+++ b/xen-hvm.c
@@ -984,19 +984,30 @@ static void handle_ioreq(XenIOState *state, ioreq_t *req)
static int handle_buffered_iopage(XenIOState *state)
{
+ buffered_iopage_t *buf_page = state->buffered_io_page;
buf_ioreq_t *buf_req = NULL;
ioreq_t req;
int qw;
- if (!state->buffered_io_page) {
+ if (!buf_page) {
return 0;
}
memset(&req, 0x00, sizeof(req));
- while (state->buffered_io_page->read_pointer !=
state->buffered_io_page->write_pointer) {
- buf_req = &state->buffered_io_page->buf_ioreq[
- state->buffered_io_page->read_pointer % IOREQ_BUFFER_SLOT_NUM];
+ for (;;) {
+ uint32_t rdptr = buf_page->read_pointer, wrptr;
+
+ xen_rmb();
+ wrptr = buf_page->write_pointer;
+ xen_rmb();
+ if (rdptr != buf_page->read_pointer) {
+ continue;
+ }
+ if (rdptr == wrptr) {
+ break;
+ }
+ buf_req = &buf_page->buf_ioreq[rdptr % IOREQ_BUFFER_SLOT_NUM];
req.size = 1UL << buf_req->size;
req.count = 1;
req.addr = buf_req->addr;
@@ -1008,15 +1019,14 @@ static int handle_buffered_iopage(XenIOState *state)
req.data_is_ptr = 0;
qw = (req.size == 8);
if (qw) {
- buf_req = &state->buffered_io_page->buf_ioreq[
- (state->buffered_io_page->read_pointer + 1) %
IOREQ_BUFFER_SLOT_NUM];
+ buf_req = &buf_page->buf_ioreq[(rdptr + 1) %
+ IOREQ_BUFFER_SLOT_NUM];
req.data |= ((uint64_t)buf_req->data) << 32;
}
handle_ioreq(state, &req);
- xen_mb();
- state->buffered_io_page->read_pointer += qw ? 2 : 1;
+ atomic_add(&buf_page->read_pointer, qw + 1);
}
return req.count;
--
1.7.10.4
- [Qemu-devel] [PULL 01/29] xen-hvm: Add trace to ioreq, (continued)
- [Qemu-devel] [PULL 01/29] xen-hvm: Add trace to ioreq, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 10/29] xen, gfx passthrough: register host bridge specific to passthrough, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 02/29] i440fx: make types configurable at run-time, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 03/29] pc_init1: pass parameters just with types, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 07/29] xen, gfx passthrough: retrieve VGA BIOS to work, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 05/29] hw/pci-assign: split pci-assign.c, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 09/29] xen, gfx passthrough: register a isa bridge, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 06/29] xen, gfx passthrough: basic graphics passthrough support, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 08/29] igd gfx passthrough: create a isa bridge, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 26/29] xen/pt: Make xen_pt_unregister_device idempotent, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 13/29] xen/HVM: atomically access pointers in bufioreq handling,
Stefano Stabellini <=
- [Qemu-devel] [PULL 12/29] xen-hvm: When using xc_domain_add_to_physmap also include errno when reporting, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 22/29] xen/pt: Check if reg->init function sets the 'data' past the reg->size, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 28/29] xen/pt: Check for return values for xen_host_pci_[get|set] in init, Stefano Stabellini, 2015/09/10
- [Qemu-devel] [PULL 21/29] xen/pt: Sync up the dev.config and data values., Stefano Stabellini, 2015/09/10
- Re: [Qemu-devel] [PULL 21/29] xen/pt: Sync up the dev.config and data values., Paolo Bonzini, 2015/09/14
- Re: [Qemu-devel] [PULL 21/29] xen/pt: Sync up the dev.config and data values., Stefano Stabellini, 2015/09/15
- Re: [Qemu-devel] [PULL 21/29] xen/pt: Sync up the dev.config and data values., Konrad Rzeszutek Wilk, 2015/09/15
- Re: [Qemu-devel] [PULL 21/29] xen/pt: Sync up the dev.config and data values., Stefano Stabellini, 2015/09/15
- Re: [Qemu-devel] [PULL 21/29] xen/pt: Sync up the dev.config and data values., Paolo Bonzini, 2015/09/15
- Re: [Qemu-devel] [PULL 21/29] xen/pt: Sync up the dev.config and data values., Konrad Rzeszutek Wilk, 2015/09/15