mirror of https://gitee.com/openkylin/qemu.git
Xen 2016/09/27
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJX6x32AAoJEIlPj0hw4a6Ql6cP/R7lNbsz34Njq6jRtE8oTNbd 4ab31WnwT2OIC+1wFWk80UlRmS6HWpF+7Ii3K/Jfgu2niJB7e2fTsPaRTl9AfSTa 6HVA3ozY/1WmOJqErngfAkTeHsmjP2uokcVfTazdIncTaErPFk37DwTG/e6gIbwY edNug5amJSzK8Podf77PaeT+SiuedFtHrV/5T9GnUXlCWj9Cq2K4HQ3yTIXg/IwG TZ5wfiaNjy7s+I6WZBxV3x4X52xtIszpvAXlb2Wzc+IQTuhLFoVXcJZNw7wA7x0b WGjwhNhTbzqBpPRRGowHCPZDoTn2tZIO5FTSHq+oN3RM0U7Wpv2fx7eb3MGISVY3 y7HUXyEDyDFaolThNB9yxj09BQBSJXtZTK+XuNxHa7so8TlS97/ugRyDThs/VVEv 1SBklk2RiqL4lE5kAe65S99Ia2Q4lS/sDxHwB54fKqdlopd4zBMWov64nTX39wze /HVZ6/BQt2DXXC2TZIAc3kE6Y+49+QODxakd1NI0kI1zjKPmTnWz+0YNXsiZ3Odx R6LpeMev3DO2tKzA5fEMRQoipyRqyWUyq10a7kyeOr5dK1w1Ov7ZH9qik45iLBD0 CyIeCfTCAeJ67wRKgWnRDSzePefWjPq5Qu6D1IPKgdxOhjsgHp67gaxYj+LMW8dx QXHiIHjjjz4N/085vyI2 =shuT -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/sstabellini/tags/xen-20160927-tag' into staging Xen 2016/09/27 # gpg: Signature made Wed 28 Sep 2016 02:33:42 BST # gpg: using RSA key 0x894F8F4870E1AE90 # gpg: Good signature from "Stefano Stabellini <sstabellini@kernel.org>" # gpg: aka "Stefano Stabellini <stefano.stabellini@eu.citrix.com>" # Primary key fingerprint: D04E 33AB A51F 67BA 07D3 0AEA 894F 8F48 70E1 AE90 * remotes/sstabellini/tags/xen-20160927-tag: qdisk - hw/block/xen_disk: grant copy implementation Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
3c87fafb90
|
@ -1952,6 +1952,61 @@ EOF
|
|||
# Xen unstable
|
||||
elif
|
||||
cat > $TMPC <<EOF &&
|
||||
/*
|
||||
* If we have stable libs the we don't want the libxc compat
|
||||
* layers, regardless of what CFLAGS we may have been given.
|
||||
*
|
||||
* Also, check if xengnttab_grant_copy_segment_t is defined and
|
||||
* grant copy operation is implemented.
|
||||
*/
|
||||
#undef XC_WANT_COMPAT_EVTCHN_API
|
||||
#undef XC_WANT_COMPAT_GNTTAB_API
|
||||
#undef XC_WANT_COMPAT_MAP_FOREIGN_API
|
||||
#include <xenctrl.h>
|
||||
#include <xenstore.h>
|
||||
#include <xenevtchn.h>
|
||||
#include <xengnttab.h>
|
||||
#include <xenforeignmemory.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 = NULL;
|
||||
xenforeignmemory_handle *xfmem;
|
||||
xenevtchn_handle *xe;
|
||||
xengnttab_handle *xg;
|
||||
xen_domain_handle_t handle;
|
||||
xengnttab_grant_copy_segment_t* seg = NULL;
|
||||
|
||||
xs_daemon_open();
|
||||
|
||||
xc = xc_interface_open(0, 0, 0);
|
||||
xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 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);
|
||||
xc_domain_create(xc, 0, handle, 0, NULL, NULL);
|
||||
|
||||
xfmem = xenforeignmemory_open(0, 0);
|
||||
xenforeignmemory_map(xfmem, 0, 0, 0, 0, 0);
|
||||
|
||||
xe = xenevtchn_open(0, 0);
|
||||
xenevtchn_fd(xe);
|
||||
|
||||
xg = xengnttab_open(0, 0);
|
||||
xengnttab_grant_copy(xg, 0, seg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
compile_prog "" "$xen_libs $xen_stable_libs"
|
||||
then
|
||||
xen_ctrl_version=480
|
||||
xen=yes
|
||||
elif
|
||||
cat > $TMPC <<EOF &&
|
||||
/*
|
||||
* If we have stable libs the we don't want the libxc compat
|
||||
* layers, regardless of what CFLAGS we may have been given.
|
||||
|
|
|
@ -119,6 +119,9 @@ struct XenBlkDev {
|
|||
unsigned int persistent_gnt_count;
|
||||
unsigned int max_grants;
|
||||
|
||||
/* Grant copy */
|
||||
gboolean feature_grant_copy;
|
||||
|
||||
/* qemu block driver */
|
||||
DriveInfo *dinfo;
|
||||
BlockBackend *blk;
|
||||
|
@ -489,6 +492,106 @@ static int ioreq_map(struct ioreq *ioreq)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_XEN_CTRL_INTERFACE_VERSION >= 480
|
||||
|
||||
static void ioreq_free_copy_buffers(struct ioreq *ioreq)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ioreq->v.niov; i++) {
|
||||
ioreq->page[i] = NULL;
|
||||
}
|
||||
|
||||
qemu_vfree(ioreq->pages);
|
||||
}
|
||||
|
||||
static int ioreq_init_copy_buffers(struct ioreq *ioreq)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ioreq->v.niov == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ioreq->pages = qemu_memalign(XC_PAGE_SIZE, ioreq->v.niov * XC_PAGE_SIZE);
|
||||
|
||||
for (i = 0; i < ioreq->v.niov; i++) {
|
||||
ioreq->page[i] = ioreq->pages + i * XC_PAGE_SIZE;
|
||||
ioreq->v.iov[i].iov_base = ioreq->page[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ioreq_grant_copy(struct ioreq *ioreq)
|
||||
{
|
||||
xengnttab_handle *gnt = ioreq->blkdev->xendev.gnttabdev;
|
||||
xengnttab_grant_copy_segment_t segs[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||
int i, count, rc;
|
||||
int64_t file_blk = ioreq->blkdev->file_blk;
|
||||
|
||||
if (ioreq->v.niov == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
count = ioreq->v.niov;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (ioreq->req.operation == BLKIF_OP_READ) {
|
||||
segs[i].flags = GNTCOPY_dest_gref;
|
||||
segs[i].dest.foreign.ref = ioreq->refs[i];
|
||||
segs[i].dest.foreign.domid = ioreq->domids[i];
|
||||
segs[i].dest.foreign.offset = ioreq->req.seg[i].first_sect * file_blk;
|
||||
segs[i].source.virt = ioreq->v.iov[i].iov_base;
|
||||
} else {
|
||||
segs[i].flags = GNTCOPY_source_gref;
|
||||
segs[i].source.foreign.ref = ioreq->refs[i];
|
||||
segs[i].source.foreign.domid = ioreq->domids[i];
|
||||
segs[i].source.foreign.offset = ioreq->req.seg[i].first_sect * file_blk;
|
||||
segs[i].dest.virt = ioreq->v.iov[i].iov_base;
|
||||
}
|
||||
segs[i].len = (ioreq->req.seg[i].last_sect
|
||||
- ioreq->req.seg[i].first_sect + 1) * file_blk;
|
||||
}
|
||||
|
||||
rc = xengnttab_grant_copy(gnt, count, segs);
|
||||
|
||||
if (rc) {
|
||||
xen_be_printf(&ioreq->blkdev->xendev, 0,
|
||||
"failed to copy data %d\n", rc);
|
||||
ioreq->aio_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (segs[i].status != GNTST_okay) {
|
||||
xen_be_printf(&ioreq->blkdev->xendev, 3,
|
||||
"failed to copy data %d for gref %d, domid %d\n",
|
||||
segs[i].status, ioreq->refs[i], ioreq->domids[i]);
|
||||
ioreq->aio_errors++;
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
#else
|
||||
static void ioreq_free_copy_buffers(struct ioreq *ioreq)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
static int ioreq_init_copy_buffers(struct ioreq *ioreq)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
static int ioreq_grant_copy(struct ioreq *ioreq)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ioreq_runio_qemu_aio(struct ioreq *ioreq);
|
||||
|
||||
static void qemu_aio_complete(void *opaque, int ret)
|
||||
|
@ -511,8 +614,31 @@ static void qemu_aio_complete(void *opaque, int ret)
|
|||
return;
|
||||
}
|
||||
|
||||
if (ioreq->blkdev->feature_grant_copy) {
|
||||
switch (ioreq->req.operation) {
|
||||
case BLKIF_OP_READ:
|
||||
/* in case of failure ioreq->aio_errors is increased */
|
||||
if (ret == 0) {
|
||||
ioreq_grant_copy(ioreq);
|
||||
}
|
||||
ioreq_free_copy_buffers(ioreq);
|
||||
break;
|
||||
case BLKIF_OP_WRITE:
|
||||
case BLKIF_OP_FLUSH_DISKCACHE:
|
||||
if (!ioreq->req.nr_segments) {
|
||||
break;
|
||||
}
|
||||
ioreq_free_copy_buffers(ioreq);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY;
|
||||
ioreq_unmap(ioreq);
|
||||
if (!ioreq->blkdev->feature_grant_copy) {
|
||||
ioreq_unmap(ioreq);
|
||||
}
|
||||
ioreq_finish(ioreq);
|
||||
switch (ioreq->req.operation) {
|
||||
case BLKIF_OP_WRITE:
|
||||
|
@ -538,8 +664,18 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
|
|||
{
|
||||
struct XenBlkDev *blkdev = ioreq->blkdev;
|
||||
|
||||
if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) {
|
||||
goto err_no_map;
|
||||
if (ioreq->blkdev->feature_grant_copy) {
|
||||
ioreq_init_copy_buffers(ioreq);
|
||||
if (ioreq->req.nr_segments && (ioreq->req.operation == BLKIF_OP_WRITE ||
|
||||
ioreq->req.operation == BLKIF_OP_FLUSH_DISKCACHE) &&
|
||||
ioreq_grant_copy(ioreq)) {
|
||||
ioreq_free_copy_buffers(ioreq);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (ioreq->req.nr_segments && ioreq_map(ioreq)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ioreq->aio_inflight++;
|
||||
|
@ -582,6 +718,9 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
|
|||
}
|
||||
default:
|
||||
/* unknown operation (shouldn't happen -- parse catches this) */
|
||||
if (!ioreq->blkdev->feature_grant_copy) {
|
||||
ioreq_unmap(ioreq);
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
@ -590,8 +729,6 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq)
|
|||
return 0;
|
||||
|
||||
err:
|
||||
ioreq_unmap(ioreq);
|
||||
err_no_map:
|
||||
ioreq_finish(ioreq);
|
||||
ioreq->status = BLKIF_RSP_ERROR;
|
||||
return -1;
|
||||
|
@ -1034,6 +1171,12 @@ static int blk_connect(struct XenDevice *xendev)
|
|||
|
||||
xen_be_bind_evtchn(&blkdev->xendev);
|
||||
|
||||
blkdev->feature_grant_copy =
|
||||
(xengnttab_grant_copy(blkdev->xendev.gnttabdev, 0, NULL) == 0);
|
||||
|
||||
xen_be_printf(&blkdev->xendev, 3, "grant copy operation %s\n",
|
||||
blkdev->feature_grant_copy ? "enabled" : "disabled");
|
||||
|
||||
xen_be_printf(&blkdev->xendev, 1, "ok: proto %s, ring-ref %d, "
|
||||
"remote port %d, local port %d\n",
|
||||
blkdev->xendev.protocol, blkdev->ring_ref,
|
||||
|
|
|
@ -424,4 +424,18 @@ static inline int xen_domain_create(xc_interface *xc, uint32_t ssidref,
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* Xen before 4.8 */
|
||||
|
||||
#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 480
|
||||
|
||||
|
||||
typedef void *xengnttab_grant_copy_segment_t;
|
||||
|
||||
static inline int xengnttab_grant_copy(xengnttab_handle *xgt, uint32_t count,
|
||||
xengnttab_grant_copy_segment_t *segs)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* QEMU_HW_XEN_COMMON_H */
|
||||
|
|
Loading…
Reference in New Issue