|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH 4/5] ioreq-server: add support for multiple servers
On 30/01/14 14:19, Paul Durrant wrote:
> The legacy 'catch-all' server is always created with id 0. Secondary
> servers will have an id ranging from 1 to a limit set by the toolstack
> via the 'max_emulators' build info field. This defaults to 1 so ordinarily
> no extra special pages are reserved for secondary emulators. It may be
> increased using the secondary_device_emulators parameter in xl.cfg(5).
>
> Because of the re-arrangement of the special pages in a previous patch we
> only need the addition of parameter HVM_PARAM_NR_IOREQ_SERVERS to determine
> the layout of the shared pages for multiple emulators. Guests migrated in
> from hosts without this patch will be lacking the save record which stores
> the new parameter and so the guest is assumed to only have had a single
> emulator.
>
> Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
> ---
> docs/man/xl.cfg.pod.5 | 7 +
> tools/libxc/xc_domain.c | 175 ++++++++
> tools/libxc/xc_domain_restore.c | 20 +
> tools/libxc/xc_domain_save.c | 12 +
> tools/libxc/xc_hvm_build_x86.c | 25 +-
> tools/libxc/xenctrl.h | 41 ++
> tools/libxc/xenguest.h | 2 +
> tools/libxc/xg_save_restore.h | 1 +
> tools/libxl/libxl.h | 8 +
> tools/libxl/libxl_create.c | 3 +
> tools/libxl/libxl_dom.c | 1 +
> tools/libxl/libxl_types.idl | 1 +
> tools/libxl/xl_cmdimpl.c | 3 +
> xen/arch/x86/hvm/hvm.c | 916
> +++++++++++++++++++++++++++++++++++---
> xen/arch/x86/hvm/io.c | 2 +-
> xen/include/asm-x86/hvm/domain.h | 21 +-
> xen/include/asm-x86/hvm/hvm.h | 1 +
> xen/include/asm-x86/hvm/vcpu.h | 2 +-
> xen/include/public/hvm/hvm_op.h | 70 +++
> xen/include/public/hvm/ioreq.h | 1 +
> xen/include/public/hvm/params.h | 4 +-
> 21 files changed, 1230 insertions(+), 86 deletions(-)
>
> diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
> index 9941395..9aa9958 100644
> --- a/docs/man/xl.cfg.pod.5
> +++ b/docs/man/xl.cfg.pod.5
> @@ -1277,6 +1277,13 @@ specified, enabling the use of XenServer PV drivers in
> the guest.
> This parameter only takes effect when device_model_version=qemu-xen.
> See F<docs/misc/pci-device-reservations.txt> for more information.
>
> +=item B<secondary_device_emulators=NUMBER>
> +
> +If a number of secondary device emulators (i.e. in addition to
> +qemu-xen or qemu-xen-traditional) are to be invoked to support the
> +guest then this parameter can be set with the count of how many are
> +to be used. The default value is zero.
> +
> =back
>
> =head2 Device-Model Options
> diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
> index c2fdd74..c64d15a 100644
> --- a/tools/libxc/xc_domain.c
> +++ b/tools/libxc/xc_domain.c
> @@ -1246,6 +1246,181 @@ int xc_get_hvm_param(xc_interface *handle, domid_t
> dom, int param, unsigned long
> return rc;
> }
>
> +int xc_hvm_create_ioreq_server(xc_interface *xch,
> + domid_t domid,
> + ioservid_t *id)
> +{
> + DECLARE_HYPERCALL;
> + DECLARE_HYPERCALL_BUFFER(xen_hvm_create_ioreq_server_t, arg);
> + int rc;
> +
> + arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
> + if ( arg == NULL )
> + return -1;
> +
> + hypercall.op = __HYPERVISOR_hvm_op;
> + hypercall.arg[0] = HVMOP_create_ioreq_server;
> + hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
> + arg->domid = domid;
> + rc = do_xen_hypercall(xch, &hypercall);
> + *id = arg->id;
> + xc_hypercall_buffer_free(xch, arg);
> + return rc;
> +}
> +
> +int xc_hvm_get_ioreq_server_info(xc_interface *xch,
> + domid_t domid,
> + ioservid_t id,
> + xen_pfn_t *pfn,
> + xen_pfn_t *buf_pfn,
> + evtchn_port_t *buf_port)
> +{
> + DECLARE_HYPERCALL;
> + DECLARE_HYPERCALL_BUFFER(xen_hvm_get_ioreq_server_info_t, arg);
> + int rc;
> +
> + arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
> + if ( arg == NULL )
> + return -1;
> +
> + hypercall.op = __HYPERVISOR_hvm_op;
> + hypercall.arg[0] = HVMOP_get_ioreq_server_info;
> + hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
> + arg->domid = domid;
> + arg->id = id;
> + rc = do_xen_hypercall(xch, &hypercall);
> + if ( rc != 0 )
> + goto done;
> +
> + if ( pfn )
> + *pfn = arg->pfn;
> +
> + if ( buf_pfn )
> + *buf_pfn = arg->buf_pfn;
> +
> + if ( buf_port )
> + *buf_port = arg->buf_port;
> +
> +done:
> + xc_hypercall_buffer_free(xch, arg);
> + return rc;
> +}
> +
> +int xc_hvm_map_io_range_to_ioreq_server(xc_interface *xch, domid_t domid,
> + ioservid_t id, int is_mmio,
> + uint64_t start, uint64_t end)
> +{
> + DECLARE_HYPERCALL;
> + DECLARE_HYPERCALL_BUFFER(xen_hvm_map_io_range_to_ioreq_server_t, arg);
> + int rc;
> +
> + arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
> + if ( arg == NULL )
> + return -1;
> +
> + hypercall.op = __HYPERVISOR_hvm_op;
> + hypercall.arg[0] = HVMOP_map_io_range_to_ioreq_server;
> + hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
> + arg->domid = domid;
> + arg->id = id;
> + arg->is_mmio = is_mmio;
> + arg->start = start;
> + arg->end = end;
> + rc = do_xen_hypercall(xch, &hypercall);
> + xc_hypercall_buffer_free(xch, arg);
> + return rc;
> +}
> +
> +int xc_hvm_unmap_io_range_from_ioreq_server(xc_interface *xch, domid_t domid,
> + ioservid_t id, int is_mmio,
> + uint64_t start)
> +{
> + DECLARE_HYPERCALL;
> + DECLARE_HYPERCALL_BUFFER(xen_hvm_unmap_io_range_from_ioreq_server_t,
> arg);
> + int rc;
> +
> + arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
> + if ( arg == NULL )
> + return -1;
> +
> + hypercall.op = __HYPERVISOR_hvm_op;
> + hypercall.arg[0] = HVMOP_unmap_io_range_from_ioreq_server;
> + hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
> + arg->domid = domid;
> + arg->id = id;
> + arg->is_mmio = is_mmio;
> + arg->start = start;
> + rc = do_xen_hypercall(xch, &hypercall);
> + xc_hypercall_buffer_free(xch, arg);
> + return rc;
> +}
> +
> +int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch, domid_t domid,
> + ioservid_t id, uint16_t bdf)
> +{
> + DECLARE_HYPERCALL;
> + DECLARE_HYPERCALL_BUFFER(xen_hvm_map_pcidev_to_ioreq_server_t, arg);
> + int rc;
> +
> + arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
> + if ( arg == NULL )
> + return -1;
> +
> + hypercall.op = __HYPERVISOR_hvm_op;
> + hypercall.arg[0] = HVMOP_map_pcidev_to_ioreq_server;
> + hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
> + arg->domid = domid;
> + arg->id = id;
> + arg->bdf = bdf;
> + rc = do_xen_hypercall(xch, &hypercall);
> + xc_hypercall_buffer_free(xch, arg);
> + return rc;
> +}
> +
> +int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface *xch, domid_t domid,
> + ioservid_t id, uint16_t bdf)
> +{
> + DECLARE_HYPERCALL;
> + DECLARE_HYPERCALL_BUFFER(xen_hvm_unmap_pcidev_from_ioreq_server_t, arg);
> + int rc;
> +
> + arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
> + if ( arg == NULL )
> + return -1;
> +
> + hypercall.op = __HYPERVISOR_hvm_op;
> + hypercall.arg[0] = HVMOP_unmap_pcidev_from_ioreq_server;
> + hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
> + arg->domid = domid;
> + arg->id = id;
> + arg->bdf = bdf;
> + rc = do_xen_hypercall(xch, &hypercall);
> + xc_hypercall_buffer_free(xch, arg);
> + return rc;
> +}
> +
> +int xc_hvm_destroy_ioreq_server(xc_interface *xch,
> + domid_t domid,
> + ioservid_t id)
> +{
> + DECLARE_HYPERCALL;
> + DECLARE_HYPERCALL_BUFFER(xen_hvm_destroy_ioreq_server_t, arg);
> + int rc;
> +
> + arg = xc_hypercall_buffer_alloc(xch, arg, sizeof(*arg));
> + if ( arg == NULL )
> + return -1;
> +
> + hypercall.op = __HYPERVISOR_hvm_op;
> + hypercall.arg[0] = HVMOP_destroy_ioreq_server;
> + hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
> + arg->domid = domid;
> + arg->id = id;
> + rc = do_xen_hypercall(xch, &hypercall);
> + xc_hypercall_buffer_free(xch, arg);
> + return rc;
> +}
> +
> int xc_domain_setdebugging(xc_interface *xch,
> uint32_t domid,
> unsigned int enable)
> diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c
> index ca2fb51..305e4b8 100644
> --- a/tools/libxc/xc_domain_restore.c
> +++ b/tools/libxc/xc_domain_restore.c
> @@ -746,6 +746,7 @@ typedef struct {
> uint64_t acpi_ioport_location;
> uint64_t viridian;
> uint64_t vm_generationid_addr;
> + uint64_t nr_ioreq_servers;
>
> struct toolstack_data_t tdata;
> } pagebuf_t;
> @@ -996,6 +997,16 @@ static int pagebuf_get_one(xc_interface *xch, struct
> restore_ctx *ctx,
> DPRINTF("read generation id buffer address");
> return pagebuf_get_one(xch, ctx, buf, fd, dom);
>
> + case XC_SAVE_ID_HVM_NR_IOREQ_SERVERS:
> + /* Skip padding 4 bytes then read the acpi ioport location. */
> + if ( RDEXACT(fd, &buf->nr_ioreq_servers, sizeof(uint32_t)) ||
> + RDEXACT(fd, &buf->nr_ioreq_servers, sizeof(uint64_t)) )
> + {
> + PERROR("error reading the number of IOREQ servers");
> + return -1;
> + }
> + return pagebuf_get_one(xch, ctx, buf, fd, dom);
> +
> default:
> if ( (count > MAX_BATCH_SIZE) || (count < 0) ) {
> ERROR("Max batch size exceeded (%d). Giving up.", count);
> @@ -1755,6 +1766,15 @@ int xc_domain_restore(xc_interface *xch, int io_fd,
> uint32_t dom,
> if (pagebuf.viridian != 0)
> xc_set_hvm_param(xch, dom, HVM_PARAM_VIRIDIAN, 1);
>
> + if ( hvm ) {
> + int nr_ioreq_servers = pagebuf.nr_ioreq_servers;
> +
> + if ( nr_ioreq_servers == 0 )
> + nr_ioreq_servers = 1;
> +
> + xc_set_hvm_param(xch, dom, HVM_PARAM_NR_IOREQ_SERVERS,
> nr_ioreq_servers);
> + }
> +
> if (pagebuf.acpi_ioport_location == 1) {
> DBGPRINTF("Use new firmware ioport from the checkpoint\n");
> xc_set_hvm_param(xch, dom, HVM_PARAM_ACPI_IOPORTS_LOCATION, 1);
> diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c
> index 42c4752..3293e29 100644
> --- a/tools/libxc/xc_domain_save.c
> +++ b/tools/libxc/xc_domain_save.c
> @@ -1731,6 +1731,18 @@ int xc_domain_save(xc_interface *xch, int io_fd,
> uint32_t dom, uint32_t max_iter
> PERROR("Error when writing the viridian flag");
> goto out;
> }
> +
> + chunk.id = XC_SAVE_ID_HVM_NR_IOREQ_SERVERS;
> + chunk.data = 0;
> + xc_get_hvm_param(xch, dom, HVM_PARAM_NR_IOREQ_SERVERS,
> + (unsigned long *)&chunk.data);
> +
> + if ( (chunk.data != 0) &&
> + wrexact(io_fd, &chunk, sizeof(chunk)) )
> + {
> + PERROR("Error when writing the number of IOREQ servers");
> + goto out;
> + }
> }
>
> if ( callbacks != NULL && callbacks->toolstack_save != NULL )
> diff --git a/tools/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c
> index f24f2a1..bbe5def 100644
> --- a/tools/libxc/xc_hvm_build_x86.c
> +++ b/tools/libxc/xc_hvm_build_x86.c
> @@ -45,7 +45,7 @@
> #define SPECIALPAGE_IDENT_PT 4
> #define SPECIALPAGE_CONSOLE 5
> #define SPECIALPAGE_IOREQ 6
> -#define NR_SPECIAL_PAGES SPECIALPAGE_IOREQ + 2 /* ioreq server needs 2
> pages */
> +#define NR_SPECIAL_PAGES(n) SPECIALPAGE_IOREQ + (2 * n) /* ioreq server
> needs 2 pages */
> #define special_pfn(x) (0xff000u - (x))
>
> static int modules_init(struct xc_hvm_build_args *args,
> @@ -83,7 +83,8 @@ static int modules_init(struct xc_hvm_build_args *args,
> }
>
> static void build_hvm_info(void *hvm_info_page, uint64_t mem_size,
> - uint64_t mmio_start, uint64_t mmio_size)
> + uint64_t mmio_start, uint64_t mmio_size,
> + int max_emulators)
> {
> struct hvm_info_table *hvm_info = (struct hvm_info_table *)
> (((unsigned char *)hvm_info_page) + HVM_INFO_OFFSET);
> @@ -111,7 +112,7 @@ static void build_hvm_info(void *hvm_info_page, uint64_t
> mem_size,
> /* Memory parameters. */
> hvm_info->low_mem_pgend = lowmem_end >> PAGE_SHIFT;
> hvm_info->high_mem_pgend = highmem_end >> PAGE_SHIFT;
> - hvm_info->reserved_mem_pgstart = special_pfn(0) - NR_SPECIAL_PAGES;
> + hvm_info->reserved_mem_pgstart = special_pfn(0) -
> NR_SPECIAL_PAGES(max_emulators);
>
> /* Finish with the checksum. */
> for ( i = 0, sum = 0; i < hvm_info->length; i++ )
> @@ -254,6 +255,10 @@ static int setup_guest(xc_interface *xch,
> stat_1gb_pages = 0;
> int pod_mode = 0;
> int claim_enabled = args->claim_enabled;
> + int max_emulators = args->max_emulators;
> +
> + if ( max_emulators < 1 )
> + goto error_out;
Is there a sane upper bound for emulators?
>
> if ( nr_pages > target_pages )
> pod_mode = XENMEMF_populate_on_demand;
> @@ -458,7 +463,8 @@ static int setup_guest(xc_interface *xch,
> xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE,
> HVM_INFO_PFN)) == NULL )
> goto error_out;
> - build_hvm_info(hvm_info_page, v_end, mmio_start, mmio_size);
> + build_hvm_info(hvm_info_page, v_end, mmio_start, mmio_size,
> + max_emulators);
> munmap(hvm_info_page, PAGE_SIZE);
>
> /* Allocate and clear special pages. */
> @@ -470,17 +476,18 @@ static int setup_guest(xc_interface *xch,
> " STORE: %"PRI_xen_pfn"\n"
> " IDENT_PT: %"PRI_xen_pfn"\n"
> " CONSOLE: %"PRI_xen_pfn"\n"
> - " IOREQ: %"PRI_xen_pfn"\n",
> - NR_SPECIAL_PAGES,
> + " IOREQ(%02d): %"PRI_xen_pfn"\n",
> + NR_SPECIAL_PAGES(max_emulators),
> (xen_pfn_t)special_pfn(SPECIALPAGE_PAGING),
> (xen_pfn_t)special_pfn(SPECIALPAGE_ACCESS),
> (xen_pfn_t)special_pfn(SPECIALPAGE_SHARING),
> (xen_pfn_t)special_pfn(SPECIALPAGE_XENSTORE),
> (xen_pfn_t)special_pfn(SPECIALPAGE_IDENT_PT),
> (xen_pfn_t)special_pfn(SPECIALPAGE_CONSOLE),
> + max_emulators * 2,
> (xen_pfn_t)special_pfn(SPECIALPAGE_IOREQ));
>
> - for ( i = 0; i < NR_SPECIAL_PAGES; i++ )
> + for ( i = 0; i < NR_SPECIAL_PAGES(max_emulators); i++ )
> {
> xen_pfn_t pfn = special_pfn(i);
> rc = xc_domain_populate_physmap_exact(xch, dom, 1, 0, 0, &pfn);
> @@ -506,7 +513,9 @@ static int setup_guest(xc_interface *xch,
> xc_set_hvm_param(xch, dom, HVM_PARAM_IOREQ_PFN,
> special_pfn(SPECIALPAGE_IOREQ));
> xc_set_hvm_param(xch, dom, HVM_PARAM_BUFIOREQ_PFN,
> - special_pfn(SPECIALPAGE_IOREQ) - 1);
> + special_pfn(SPECIALPAGE_IOREQ) - max_emulators);
> + xc_set_hvm_param(xch, dom, HVM_PARAM_NR_IOREQ_SERVERS,
> + max_emulators);
>
> /*
> * Identity-map page table is required for running with CR0.PG=0 when
> diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
> index 13f816b..142aaea 100644
> --- a/tools/libxc/xenctrl.h
> +++ b/tools/libxc/xenctrl.h
> @@ -1801,6 +1801,47 @@ void xc_clear_last_error(xc_interface *xch);
> int xc_set_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned
> long value);
> int xc_get_hvm_param(xc_interface *handle, domid_t dom, int param, unsigned
> long *value);
>
> +/*
> + * IOREQ server API
> + */
> +int xc_hvm_create_ioreq_server(xc_interface *xch,
> + domid_t domid,
> + ioservid_t *id);
> +
> +int xc_hvm_get_ioreq_server_info(xc_interface *xch,
> + domid_t domid,
> + ioservid_t id,
> + xen_pfn_t *pfn,
> + xen_pfn_t *buf_pfn,
> + evtchn_port_t *buf_port);
> +
> +int xc_hvm_map_io_range_to_ioreq_server(xc_interface *xch,
> + domid_t domid,
> + ioservid_t id,
> + int is_mmio,
> + uint64_t start,
> + uint64_t end);
> +
> +int xc_hvm_unmap_io_range_from_ioreq_server(xc_interface *xch,
> + domid_t domid,
> + ioservid_t id,
> + int is_mmio,
> + uint64_t start);
> +
> +int xc_hvm_map_pcidev_to_ioreq_server(xc_interface *xch,
> + domid_t domid,
> + ioservid_t id,
> + uint16_t bdf);
> +
> +int xc_hvm_unmap_pcidev_from_ioreq_server(xc_interface *xch,
> + domid_t domid,
> + ioservid_t id,
> + uint16_t bdf);
> +
> +int xc_hvm_destroy_ioreq_server(xc_interface *xch,
> + domid_t domid,
> + ioservid_t id);
> +
There are tab/space issues in this hunk.
> /* HVM guest pass-through */
> int xc_assign_device(xc_interface *xch,
> uint32_t domid,
> diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h
> index a0e30e1..8930ac0 100644
> --- a/tools/libxc/xenguest.h
> +++ b/tools/libxc/xenguest.h
> @@ -234,6 +234,8 @@ struct xc_hvm_build_args {
> struct xc_hvm_firmware_module smbios_module;
> /* Whether to use claim hypercall (1 - enable, 0 - disable). */
> int claim_enabled;
> + /* Maximum number of emulators for VM */
> + int max_emulators;
> };
>
> /**
> diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h
> index f859621..5170b7f 100644
> --- a/tools/libxc/xg_save_restore.h
> +++ b/tools/libxc/xg_save_restore.h
> @@ -259,6 +259,7 @@
> #define XC_SAVE_ID_HVM_ACCESS_RING_PFN -16
> #define XC_SAVE_ID_HVM_SHARING_RING_PFN -17
> #define XC_SAVE_ID_TOOLSTACK -18 /* Optional toolstack specific
> info */
> +#define XC_SAVE_ID_HVM_NR_IOREQ_SERVERS -19
>
> /*
> ** We process save/restore/migrate in batches of pages; the below
> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index 12d6c31..b679957 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -95,6 +95,14 @@
> #define LIBXL_HAVE_BUILDINFO_EVENT_CHANNELS 1
>
> /*
> + * LIBXL_HAVE_BUILDINFO_HVM_MAX_EMULATORS indicates that the
> + * max_emulators field is present in the hvm sections of
> + * libxl_domain_build_info. This field can be used to reserve
> + * extra special pages for secondary device emulators.
> + */
> +#define LIBXL_HAVE_BUILDINFO_HVM_MAX_EMULATORS 1
> +
> +/*
> * libxl ABI compatibility
> *
> * The only guarantee which libxl makes regarding ABI compatibility
> diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
> index a604cd8..cce93d9 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> @@ -330,6 +330,9 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
>
> libxl_defbool_setdefault(&b_info->u.hvm.gfx_passthru, false);
>
> + if (b_info->u.hvm.max_emulators < 1)
> + b_info->u.hvm.max_emulators = 1;
> +
> break;
> case LIBXL_DOMAIN_TYPE_PV:
> libxl_defbool_setdefault(&b_info->u.pv.e820_host, false);
> diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> index 55f74b2..9de06f9 100644
> --- a/tools/libxl/libxl_dom.c
> +++ b/tools/libxl/libxl_dom.c
> @@ -637,6 +637,7 @@ int libxl__build_hvm(libxl__gc *gc, uint32_t domid,
> args.mem_size = (uint64_t)(info->max_memkb - info->video_memkb) << 10;
> args.mem_target = (uint64_t)(info->target_memkb - info->video_memkb) <<
> 10;
> args.claim_enabled = libxl_defbool_val(info->claim_mode);
> + args.max_emulators = info->u.hvm.max_emulators;
> if (libxl__domain_firmware(gc, info, &args)) {
> LOG(ERROR, "initializing domain firmware failed");
> goto out;
> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> index 649ce50..b707159 100644
> --- a/tools/libxl/libxl_types.idl
> +++ b/tools/libxl/libxl_types.idl
> @@ -372,6 +372,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
> ("xen_platform_pci", libxl_defbool),
> ("usbdevice_list",
> libxl_string_list),
> ("vendor_device",
> libxl_vendor_device),
> + ("max_emulators", integer),
> ])),
> ("pv", Struct(None, [("kernel", string),
> ("slack_memkb", MemKB),
> diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
> index aff6f90..c65f4f4 100644
> --- a/tools/libxl/xl_cmdimpl.c
> +++ b/tools/libxl/xl_cmdimpl.c
> @@ -1750,6 +1750,9 @@ skip_vfb:
>
> b_info->u.hvm.vendor_device = d;
> }
> +
> + if (!xlu_cfg_get_long (config, "secondary_device_emulators", &l, 0))
> + b_info->u.hvm.max_emulators = l + 1;
> }
>
> xlu_cfg_destroy(config);
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index d9874fb..5f9e728 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -379,21 +379,23 @@ static void hvm_wait_on_io(struct domain *d, ioreq_t *p)
> void hvm_do_resume(struct vcpu *v)
> {
> struct domain *d = v->domain;
> - struct hvm_ioreq_server *s;
> + struct list_head *entry, *next;
>
> check_wakeup_from_wait();
>
> if ( is_hvm_vcpu(v) )
> pt_restore_timer(v);
>
> - s = v->arch.hvm_vcpu.ioreq_server;
> - v->arch.hvm_vcpu.ioreq_server = NULL;
> -
> - if ( s )
> + list_for_each_safe ( entry, next, &v->arch.hvm_vcpu.ioreq_server_list )
> {
> + struct hvm_ioreq_server *s = list_entry(entry,
> + struct hvm_ioreq_server,
> + vcpu_list_entry[v->vcpu_id]);
> ioreq_t *p = get_ioreq(s, v->vcpu_id);
>
> hvm_wait_on_io(d, p);
> +
> + list_del_init(entry);
> }
>
> /* Inject pending hw/sw trap */
> @@ -531,6 +533,83 @@ static int hvm_print_line(
> return X86EMUL_OKAY;
> }
>
> +static int hvm_access_cf8(
> + int dir, uint32_t port, uint32_t bytes, uint32_t *val)
> +{
> + struct vcpu *curr = current;
> + struct hvm_domain *hd = &curr->domain->arch.hvm_domain;
> + int rc;
> +
> + BUG_ON(port < 0xcf8);
> + port -= 0xcf8;
> +
> + spin_lock(&hd->pci_lock);
> +
> + if ( dir == IOREQ_WRITE )
> + {
> + switch ( bytes )
> + {
> + case 4:
> + hd->pci_cf8 = *val;
> + break;
> +
> + case 2:
> + {
> + uint32_t mask = 0xffff << (port * 8);
> + uint32_t subval = *val << (port * 8);
> +
> + hd->pci_cf8 = (hd->pci_cf8 & ~mask) |
> + (subval & mask);
> + break;
> + }
> +
> + case 1:
> + {
> + uint32_t mask = 0xff << (port * 8);
> + uint32_t subval = *val << (port * 8);
> +
> + hd->pci_cf8 = (hd->pci_cf8 & ~mask) |
> + (subval & mask);
> + break;
> + }
> +
> + default:
> + break;
> + }
> +
> + /* We always need to fall through to the catch all emulator */
> + rc = X86EMUL_UNHANDLEABLE;
> + }
> + else
> + {
> + switch ( bytes )
> + {
> + case 4:
> + *val = hd->pci_cf8;
> + rc = X86EMUL_OKAY;
> + break;
> +
> + case 2:
> + *val = (hd->pci_cf8 >> (port * 8)) & 0xffff;
> + rc = X86EMUL_OKAY;
> + break;
> +
> + case 1:
> + *val = (hd->pci_cf8 >> (port * 8)) & 0xff;
> + rc = X86EMUL_OKAY;
> + break;
> +
> + default:
> + rc = X86EMUL_UNHANDLEABLE;
> + break;
> + }
> + }
> +
> + spin_unlock(&hd->pci_lock);
> +
> + return rc;
> +}
> +
> static int handle_pvh_io(
> int dir, uint32_t port, uint32_t bytes, uint32_t *val)
> {
> @@ -590,6 +669,8 @@ done:
>
> static void hvm_ioreq_server_remove_vcpu(struct hvm_ioreq_server *s, struct
> vcpu *v)
> {
> + list_del_init(&s->vcpu_list_entry[v->vcpu_id]);
> +
> if ( v->vcpu_id == 0 )
> {
> if ( s->buf_ioreq_evtchn >= 0 )
> @@ -606,7 +687,7 @@ static void hvm_ioreq_server_remove_vcpu(struct
> hvm_ioreq_server *s, struct vcpu
> }
> }
>
> -static int hvm_create_ioreq_server(struct domain *d, domid_t domid)
> +static int hvm_create_ioreq_server(struct domain *d, ioservid_t id, domid_t
> domid)
> {
> struct hvm_ioreq_server *s;
> int i;
> @@ -614,34 +695,47 @@ static int hvm_create_ioreq_server(struct domain *d,
> domid_t domid)
> struct vcpu *v;
> int rc;
>
> + if ( id >= d->arch.hvm_domain.params[HVM_PARAM_NR_IOREQ_SERVERS] )
> + return -EINVAL;
> +
> spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
>
> rc = -EEXIST;
> - if ( d->arch.hvm_domain.ioreq_server != NULL )
> - goto fail_exist;
> + list_for_each_entry ( s,
> + &d->arch.hvm_domain.ioreq_server_list,
> + domain_list_entry )
> + {
> + if ( s->id == id )
> + goto fail_exist;
> + }
>
> - gdprintk(XENLOG_INFO, "%s: %d\n", __func__, d->domain_id);
> + gdprintk(XENLOG_INFO, "%s: %d:%d\n", __func__, d->domain_id, id);
>
> rc = -ENOMEM;
> s = xzalloc(struct hvm_ioreq_server);
> if ( !s )
> goto fail_alloc;
>
> + s->id = id;
> s->domain = d;
> s->domid = domid;
> + INIT_LIST_HEAD(&s->domain_list_entry);
>
> for ( i = 0; i < MAX_HVM_VCPUS; i++ )
> + {
> s->ioreq_evtchn[i] = -1;
> + INIT_LIST_HEAD(&s->vcpu_list_entry[i]);
> + }
> s->buf_ioreq_evtchn = -1;
>
> /* Initialize shared pages */
> - pfn = d->arch.hvm_domain.params[HVM_PARAM_IOREQ_PFN];
> + pfn = d->arch.hvm_domain.params[HVM_PARAM_IOREQ_PFN] - s->id;
>
> hvm_init_ioreq_page(s, 0);
> if ( (rc = hvm_set_ioreq_page(s, 0, pfn)) < 0 )
> goto fail_set_ioreq;
>
> - pfn = d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_PFN];
> + pfn = d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_PFN] - s->id;
>
> hvm_init_ioreq_page(s, 1);
> if ( (rc = hvm_set_ioreq_page(s, 1, pfn)) < 0 )
> @@ -653,7 +747,8 @@ static int hvm_create_ioreq_server(struct domain *d,
> domid_t domid)
> goto fail_add_vcpu;
> }
>
> - d->arch.hvm_domain.ioreq_server = s;
> + list_add(&s->domain_list_entry,
> + &d->arch.hvm_domain.ioreq_server_list);
>
> spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
>
> @@ -673,22 +768,30 @@ fail_exist:
> return rc;
> }
>
> -static void hvm_destroy_ioreq_server(struct domain *d)
> +static void hvm_destroy_ioreq_server(struct domain *d, ioservid_t id)
> {
> - struct hvm_ioreq_server *s;
> + struct hvm_ioreq_server *s, *next;
> struct vcpu *v;
>
> spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
>
> - gdprintk(XENLOG_INFO, "%s: %d\n", __func__, d->domain_id);
> + list_for_each_entry_safe ( s,
> + next,
> + &d->arch.hvm_domain.ioreq_server_list,
> + domain_list_entry)
> + {
> + if ( s->id == id )
> + goto found;
> + }
>
> - s = d->arch.hvm_domain.ioreq_server;
> - if ( !s )
> - goto done;
> + goto done;
> +
> +found:
> + gdprintk(XENLOG_INFO, "%s: %d:%d\n", __func__, d->domain_id, id);
>
> domain_pause(d);
>
> - d->arch.hvm_domain.ioreq_server = NULL;
> + list_del_init(&s->domain_list_entry);
>
> for_each_vcpu ( d, v )
> hvm_ioreq_server_remove_vcpu(s, v);
> @@ -704,21 +807,186 @@ done:
> spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> }
>
> -static int hvm_get_ioreq_server_buf_port(struct domain *d, evtchn_port_t
> *port)
> +static int hvm_get_ioreq_server_buf_port(struct domain *d, ioservid_t id,
> evtchn_port_t *port)
> +{
> + struct list_head *entry;
> + int rc;
> +
> + if ( id >= d->arch.hvm_domain.params[HVM_PARAM_NR_IOREQ_SERVERS] )
> + return -EINVAL;
> +
> + spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + rc = -ENOENT;
> + list_for_each ( entry,
> + &d->arch.hvm_domain.ioreq_server_list )
> + {
> + struct hvm_ioreq_server *s = list_entry(entry,
> + struct hvm_ioreq_server,
> + domain_list_entry);
> +
> + if ( s->id == id )
> + {
> + *port = s->buf_ioreq_evtchn;
> + rc = 0;
> + break;
> + }
> + }
> +
> + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + return rc;
> +}
> +
> +static int hvm_get_ioreq_server_pfn(struct domain *d, ioservid_t id, int
> buf, xen_pfn_t *pfn)
> +{
> + struct list_head *entry;
> + int rc;
> +
> + if ( id >= d->arch.hvm_domain.params[HVM_PARAM_NR_IOREQ_SERVERS] )
> + return -EINVAL;
> +
> + spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + rc = -ENOENT;
> + list_for_each ( entry,
> + &d->arch.hvm_domain.ioreq_server_list )
> + {
> + struct hvm_ioreq_server *s = list_entry(entry,
> + struct hvm_ioreq_server,
> + domain_list_entry);
> +
> + if ( s->id == id )
> + {
> + if ( buf )
> + *pfn = d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_PFN] -
> s->id;
> + else
> + *pfn = d->arch.hvm_domain.params[HVM_PARAM_IOREQ_PFN] -
> s->id;
> +
> + rc = 0;
> + break;
> + }
> + }
> +
> + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + return rc;
> +}
> +
> +static int hvm_map_io_range_to_ioreq_server(struct domain *d, ioservid_t id,
> + int is_mmio, uint64_t start,
> uint64_t end)
> {
> struct hvm_ioreq_server *s;
> + struct hvm_io_range *x;
> int rc;
>
> + if ( id >= d->arch.hvm_domain.params[HVM_PARAM_NR_IOREQ_SERVERS] )
> + return -EINVAL;
> +
> + x = xmalloc(struct hvm_io_range);
> + if ( x == NULL )
> + return -ENOMEM;
> +
> spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
>
> - s = d->arch.hvm_domain.ioreq_server;
> + rc = -ENOENT;
> + list_for_each_entry ( s,
> + &d->arch.hvm_domain.ioreq_server_list,
> + domain_list_entry )
> + {
> + if ( s->id == id )
> + goto found;
> + }
> +
> + goto fail;
> +
> +found:
> + x->start = start;
> + x->end = end;
> +
> + if ( is_mmio )
> + {
> + x->next = s->mmio_range_list;
> + s->mmio_range_list = x;
> + }
> + else
> + {
> + x->next = s->portio_range_list;
> + s->portio_range_list = x;
> + }
> +
> + gdprintk(XENLOG_DEBUG, "%d:%d: +%s %"PRIX64" - %"PRIX64"\n",
> + d->domain_id,
> + s->id,
> + ( is_mmio ) ? "MMIO" : "PORTIO",
> + x->start,
> + x->end);
> +
> + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + return 0;
> +
> +fail:
> + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> + xfree(x);
> +
> + return rc;
> +}
> +
> +static int hvm_unmap_io_range_from_ioreq_server(struct domain *d, ioservid_t
> id,
> + int is_mmio, uint64_t start)
> +{
> + struct hvm_ioreq_server *s;
> + struct hvm_io_range *x, **xp;
> + int rc;
> +
> + if ( id >= d->arch.hvm_domain.params[HVM_PARAM_NR_IOREQ_SERVERS] )
> + return -EINVAL;
> +
> + spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
>
> rc = -ENOENT;
> - if ( !s )
> - goto done;
> + list_for_each_entry ( s,
> + &d->arch.hvm_domain.ioreq_server_list,
> + domain_list_entry )
> + {
> + if ( s->id == id )
> + goto found;
> + }
>
> - *port = s->buf_ioreq_evtchn;
> - rc = 0;
> + goto done;
> +
> +found:
> + if ( is_mmio )
> + {
> + x = s->mmio_range_list;
> + xp = &s->mmio_range_list;
> + }
> + else
> + {
> + x = s->portio_range_list;
> + xp = &s->portio_range_list;
> + }
> +
> + while ( (x != NULL) && (start != x->start) )
> + {
> + xp = &x->next;
> + x = x->next;
> + }
> +
> + if ( (x != NULL) )
> + {
> + gdprintk(XENLOG_DEBUG, "%d:%d: -%s %"PRIX64" - %"PRIX64"\n",
> + d->domain_id,
> + s->id,
> + ( is_mmio ) ? "MMIO" : "PORTIO",
> + x->start,
> + x->end);
> +
> + *xp = x->next;
> + xfree(x);
> + rc = 0;
> + }
>
> done:
> spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> @@ -726,25 +994,98 @@ done:
> return rc;
> }
>
> -static int hvm_get_ioreq_server_pfn(struct domain *d, int buf, xen_pfn_t
> *pfn)
> +static int hvm_map_pcidev_to_ioreq_server(struct domain *d, ioservid_t id,
> + uint16_t bdf)
> {
> struct hvm_ioreq_server *s;
> + struct hvm_pcidev *x;
> int rc;
>
> + if ( id >= d->arch.hvm_domain.params[HVM_PARAM_NR_IOREQ_SERVERS] )
> + return -EINVAL;
> +
> + x = xmalloc(struct hvm_pcidev);
> + if ( x == NULL )
> + return -ENOMEM;
> +
> spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
>
> - s = d->arch.hvm_domain.ioreq_server;
> + rc = -ENOENT;
> + list_for_each_entry ( s,
> + &d->arch.hvm_domain.ioreq_server_list,
> + domain_list_entry )
> + {
> + if ( s->id == id )
> + goto found;
> + }
> +
> + goto fail;
> +
> +found:
> + x->bdf = bdf;
> +
> + x->next = s->pcidev_list;
> + s->pcidev_list = x;
> +
> + gdprintk(XENLOG_DEBUG, "%d:%d: +PCIDEV %04X\n",
> + d->domain_id,
> + s->id,
> + x->bdf);
> +
> + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + return 0;
> +
> +fail:
> + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> + xfree(x);
> +
> + return rc;
> +}
> +
> +static int hvm_unmap_pcidev_from_ioreq_server(struct domain *d, ioservid_t
> id,
> + uint16_t bdf)
> +{
> + struct hvm_ioreq_server *s;
> + struct hvm_pcidev *x, **xp;
> + int rc;
> +
> + if ( id >= d->arch.hvm_domain.params[HVM_PARAM_NR_IOREQ_SERVERS] )
> + return -EINVAL;
> +
> + spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
>
> rc = -ENOENT;
> - if ( !s )
> - goto done;
> + list_for_each_entry ( s,
> + &d->arch.hvm_domain.ioreq_server_list,
> + domain_list_entry )
> + {
> + if ( s->id == id )
> + goto found;
> + }
>
> - if ( buf )
> - *pfn = d->arch.hvm_domain.params[HVM_PARAM_BUFIOREQ_PFN];
> - else
> - *pfn = d->arch.hvm_domain.params[HVM_PARAM_IOREQ_PFN];
> + goto done;
>
> - rc = 0;
> +found:
> + x = s->pcidev_list;
> + xp = &s->pcidev_list;
> +
> + while ( (x != NULL) && (bdf != x->bdf) )
> + {
> + xp = &x->next;
> + x = x->next;
> + }
> + if ( (x != NULL) )
> + {
> + gdprintk(XENLOG_DEBUG, "%d:%d: -PCIDEV %04X\n",
> + d->domain_id,
> + s->id,
> + x->bdf);
> +
> + *xp = x->next;
> + xfree(x);
> + rc = 0;
> + }
>
> done:
> spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> @@ -752,6 +1093,73 @@ done:
> return rc;
> }
>
> +static int hvm_all_ioreq_servers_add_vcpu(struct domain *d, struct vcpu *v)
> +{
> + struct list_head *entry;
> + int rc;
> +
> + spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + list_for_each ( entry,
> + &d->arch.hvm_domain.ioreq_server_list )
> + {
> + struct hvm_ioreq_server *s = list_entry(entry,
> + struct hvm_ioreq_server,
> + domain_list_entry);
> +
> + if ( (rc = hvm_ioreq_server_add_vcpu(s, v)) < 0 )
> + goto fail;
> + }
> +
> + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + return 0;
> +
> +fail:
> + list_for_each ( entry,
> + &d->arch.hvm_domain.ioreq_server_list )
> + {
> + struct hvm_ioreq_server *s = list_entry(entry,
> + struct hvm_ioreq_server,
> + domain_list_entry);
> +
> + hvm_ioreq_server_remove_vcpu(s, v);
> + }
> +
> + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + return rc;
> +}
> +
> +static void hvm_all_ioreq_servers_remove_vcpu(struct domain *d, struct vcpu
> *v)
> +{
> + struct list_head *entry;
> +
> + spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + list_for_each ( entry,
> + &d->arch.hvm_domain.ioreq_server_list )
> + {
> + struct hvm_ioreq_server *s = list_entry(entry,
> + struct hvm_ioreq_server,
> + domain_list_entry);
> +
> + hvm_ioreq_server_remove_vcpu(s, v);
> + }
> +
> + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> +}
> +
> +static void hvm_destroy_all_ioreq_servers(struct domain *d)
> +{
> + ioservid_t id;
> +
> + for ( id = 0;
> + id < d->arch.hvm_domain.params[HVM_PARAM_NR_IOREQ_SERVERS];
> + id++ )
> + hvm_destroy_ioreq_server(d, id);
> +}
> +
> static int hvm_replace_event_channel(struct vcpu *v, domid_t remote_domid,
> int *p_port)
> {
> @@ -767,21 +1175,30 @@ static int hvm_replace_event_channel(struct vcpu *v,
> domid_t remote_domid,
> return 0;
> }
>
> -static int hvm_set_ioreq_server_domid(struct domain *d, domid_t domid)
> +static int hvm_set_ioreq_server_domid(struct domain *d, ioservid_t id,
> domid_t domid)
> {
> struct hvm_ioreq_server *s;
> struct vcpu *v;
> int rc = 0;
>
> + if ( id >= d->arch.hvm_domain.params[HVM_PARAM_NR_IOREQ_SERVERS] )
> + return -EINVAL;
> +
> domain_pause(d);
> spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
>
> - s = d->arch.hvm_domain.ioreq_server;
> + list_for_each_entry ( s,
> + &d->arch.hvm_domain.ioreq_server_list,
> + domain_list_entry )
> + {
> + if ( s->id == id )
> + goto found;
> + }
>
> rc = -ENOENT;
> - if ( !s )
> - goto done;
> + goto done;
>
> +found:
> rc = 0;
> if ( s->domid == domid )
> goto done;
> @@ -838,7 +1255,9 @@ int hvm_domain_initialise(struct domain *d)
>
> }
>
> + INIT_LIST_HEAD(&d->arch.hvm_domain.ioreq_server_list);
> spin_lock_init(&d->arch.hvm_domain.ioreq_server_lock);
> + spin_lock_init(&d->arch.hvm_domain.pci_lock);
> spin_lock_init(&d->arch.hvm_domain.irq_lock);
> spin_lock_init(&d->arch.hvm_domain.uc_lock);
>
> @@ -880,6 +1299,7 @@ int hvm_domain_initialise(struct domain *d)
> rtc_init(d);
>
> register_portio_handler(d, 0xe9, 1, hvm_print_line);
> + register_portio_handler(d, 0xcf8, 4, hvm_access_cf8);
>
> rc = hvm_funcs.domain_initialise(d);
> if ( rc != 0 )
> @@ -910,7 +1330,7 @@ void hvm_domain_relinquish_resources(struct domain *d)
> if ( hvm_funcs.nhvm_domain_relinquish_resources )
> hvm_funcs.nhvm_domain_relinquish_resources(d);
>
> - hvm_destroy_ioreq_server(d);
> + hvm_destroy_all_ioreq_servers(d);
>
> msixtbl_pt_cleanup(d);
>
> @@ -1422,13 +1842,14 @@ int hvm_vcpu_initialise(struct vcpu *v)
> {
> int rc;
> struct domain *d = v->domain;
> - struct hvm_ioreq_server *s;
>
> hvm_asid_flush_vcpu(v);
>
> spin_lock_init(&v->arch.hvm_vcpu.tm_lock);
> INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list);
>
> + INIT_LIST_HEAD(&v->arch.hvm_vcpu.ioreq_server_list);
> +
> rc = hvm_vcpu_cacheattr_init(v); /* teardown: vcpu_cacheattr_destroy */
> if ( rc != 0 )
> goto fail1;
> @@ -1465,16 +1886,9 @@ int hvm_vcpu_initialise(struct vcpu *v)
> && (rc = nestedhvm_vcpu_initialise(v)) < 0 ) /* teardown:
> nestedhvm_vcpu_destroy */
> goto fail5;
>
> - spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
> - s = d->arch.hvm_domain.ioreq_server;
> - spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> -
> - if ( s )
> - {
> - rc = hvm_ioreq_server_add_vcpu(s, v);
> - if ( rc < 0 )
> - goto fail6;
> - }
> + rc = hvm_all_ioreq_servers_add_vcpu(d, v);
> + if ( rc < 0 )
> + goto fail6;
>
> if ( v->vcpu_id == 0 )
> {
> @@ -1510,14 +1924,8 @@ int hvm_vcpu_initialise(struct vcpu *v)
> void hvm_vcpu_destroy(struct vcpu *v)
> {
> struct domain *d = v->domain;
> - struct hvm_ioreq_server *s;
> -
> - spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
> - s = d->arch.hvm_domain.ioreq_server;
> - spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
>
> - if ( s )
> - hvm_ioreq_server_remove_vcpu(s, v);
> + hvm_all_ioreq_servers_remove_vcpu(d, v);
>
> nestedhvm_vcpu_destroy(v);
>
> @@ -1556,6 +1964,101 @@ void hvm_vcpu_down(struct vcpu *v)
> }
> }
>
> +static struct hvm_ioreq_server *hvm_select_ioreq_server(struct vcpu *v,
> ioreq_t *p)
> +{
> +#define BDF(cf8) (((cf8) & 0x00ffff00) >> 8)
> +
> + struct domain *d = v->domain;
> + struct hvm_ioreq_server *s;
> + uint8_t type;
> + uint64_t addr;
> +
> + if ( p->type == IOREQ_TYPE_PIO &&
> + (p->addr & ~3) == 0xcfc )
> + {
> + /* PCI config data cycle */
> + type = IOREQ_TYPE_PCI_CONFIG;
> +
> + spin_lock(&d->arch.hvm_domain.pci_lock);
> + addr = d->arch.hvm_domain.pci_cf8 + (p->addr & 3);
> + spin_unlock(&d->arch.hvm_domain.pci_lock);
> + }
> + else
> + {
> + type = p->type;
> + addr = p->addr;
> + }
> +
> + spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + switch ( type )
> + {
> + case IOREQ_TYPE_COPY:
> + case IOREQ_TYPE_PIO:
> + case IOREQ_TYPE_PCI_CONFIG:
> + break;
> + default:
> + goto done;
> + }
> +
> + list_for_each_entry ( s,
> + &d->arch.hvm_domain.ioreq_server_list,
> + domain_list_entry )
> + {
> + switch ( type )
> + {
> + case IOREQ_TYPE_COPY:
> + case IOREQ_TYPE_PIO: {
> + struct hvm_io_range *x;
> +
> + x = (type == IOREQ_TYPE_COPY) ?
> + s->mmio_range_list :
> + s->portio_range_list;
> +
> + for ( ; x; x = x->next )
> + {
> + if ( (addr >= x->start) && (addr <= x->end) )
> + goto found;
> + }
> + break;
> + }
> + case IOREQ_TYPE_PCI_CONFIG: {
> + struct hvm_pcidev *x;
> +
> + x = s->pcidev_list;
> +
> + for ( ; x; x = x->next )
> + {
> + if ( BDF(addr) == x->bdf ) {
> + p->type = type;
> + p->addr = addr;
> + goto found;
> + }
> + }
> + break;
> + }
> + }
> + }
> +
> +done:
> + /* The catch-all server has id 0 */
> + list_for_each_entry ( s,
> + &d->arch.hvm_domain.ioreq_server_list,
> + domain_list_entry )
> + {
> + if ( s->id == 0 )
> + goto found;
> + }
> +
> + s = NULL;
> +
> +found:
> + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> + return s;
> +
> +#undef BDF
> +}
> +
> int hvm_buffered_io_send(ioreq_t *p)
> {
> struct vcpu *v = current;
> @@ -1570,10 +2073,7 @@ int hvm_buffered_io_send(ioreq_t *p)
> /* Ensure buffered_iopage fits in a page */
> BUILD_BUG_ON(sizeof(buffered_iopage_t) > PAGE_SIZE);
>
> - spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
> - s = d->arch.hvm_domain.ioreq_server;
> - spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> -
> + s = hvm_select_ioreq_server(v, p);
> if ( !s )
> return 0;
>
> @@ -1661,7 +2161,9 @@ static bool_t hvm_send_assist_req_to_server(struct
> hvm_ioreq_server *s,
> return 0;
> }
>
> - v->arch.hvm_vcpu.ioreq_server = s;
> + ASSERT(list_empty(&s->vcpu_list_entry[v->vcpu_id]));
> + list_add(&s->vcpu_list_entry[v->vcpu_id],
> + &v->arch.hvm_vcpu.ioreq_server_list);
>
> p->dir = proto_p->dir;
> p->data_is_ptr = proto_p->data_is_ptr;
> @@ -1686,24 +2188,42 @@ static bool_t hvm_send_assist_req_to_server(struct
> hvm_ioreq_server *s,
>
> bool_t hvm_send_assist_req(struct vcpu *v, ioreq_t *p)
> {
> - struct domain *d = v->domain;
> struct hvm_ioreq_server *s;
>
> - ASSERT(v->arch.hvm_vcpu.ioreq_server == NULL);
> + ASSERT(list_empty(&v->arch.hvm_vcpu.ioreq_server_list));
>
> if ( unlikely(!vcpu_start_shutdown_deferral(v)) )
> return 0;
>
> - spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
> - s = d->arch.hvm_domain.ioreq_server;
> - spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> -
> + s = hvm_select_ioreq_server(v, p);
> if ( !s )
> return 0;
>
> return hvm_send_assist_req_to_server(s, v, p);
> }
>
> +void hvm_broadcast_assist_req(struct vcpu *v, ioreq_t *p)
> +{
> + struct domain *d = v->domain;
> + struct list_head *entry;
> +
> + ASSERT(list_empty(&v->arch.hvm_vcpu.ioreq_server_list));
> +
> + spin_lock(&d->arch.hvm_domain.ioreq_server_lock);
> +
> + list_for_each ( entry,
> + &d->arch.hvm_domain.ioreq_server_list )
> + {
> + struct hvm_ioreq_server *s = list_entry(entry,
> + struct hvm_ioreq_server,
> + domain_list_entry);
> +
> + (void) hvm_send_assist_req_to_server(s, v, p);
> + }
> +
> + spin_unlock(&d->arch.hvm_domain.ioreq_server_lock);
> +}
> +
> void hvm_hlt(unsigned long rflags)
> {
> struct vcpu *curr = current;
> @@ -4286,6 +4806,215 @@ static int hvmop_flush_tlb_all(void)
> return 0;
> }
>
> +static int hvmop_create_ioreq_server(
> + XEN_GUEST_HANDLE_PARAM(xen_hvm_create_ioreq_server_t) uop)
> +{
> + struct domain *curr_d = current->domain;
> + xen_hvm_create_ioreq_server_t op;
> + struct domain *d;
> + ioservid_t id;
> + int rc;
> +
> + if ( copy_from_guest(&op, uop, 1) )
> + return -EFAULT;
> +
> + rc = rcu_lock_remote_domain_by_id(op.domid, &d);
> + if ( rc != 0 )
> + return rc;
> +
> + rc = -EINVAL;
> + if ( !is_hvm_domain(d) )
> + goto out;
> +
> + rc = -ENOSPC;
> + for ( id = 1;
> + id < d->arch.hvm_domain.params[HVM_PARAM_NR_IOREQ_SERVERS];
> + id++ )
> + {
> + rc = hvm_create_ioreq_server(d, id, curr_d->domain_id);
> + if ( rc == -EEXIST )
> + continue;
> +
> + break;
> + }
> +
> + if ( rc == -EEXIST )
> + rc = -ENOSPC;
> +
> + if ( rc < 0 )
> + goto out;
> +
> + op.id = id;
> +
> + rc = copy_to_guest(uop, &op, 1) ? -EFAULT : 0;
> +
> +out:
> + rcu_unlock_domain(d);
> + return rc;
> +}
> +
> +static int hvmop_get_ioreq_server_info(
> + XEN_GUEST_HANDLE_PARAM(xen_hvm_get_ioreq_server_info_t) uop)
> +{
> + xen_hvm_get_ioreq_server_info_t op;
> + struct domain *d;
> + int rc;
> +
> + if ( copy_from_guest(&op, uop, 1) )
> + return -EFAULT;
> +
> + rc = rcu_lock_remote_domain_by_id(op.domid, &d);
> + if ( rc != 0 )
> + return rc;
> +
> + rc = -EINVAL;
> + if ( !is_hvm_domain(d) )
> + goto out;
> +
> + if ( (rc = hvm_get_ioreq_server_pfn(d, op.id, 0, &op.pfn)) < 0 )
> + goto out;
> +
> + if ( (rc = hvm_get_ioreq_server_pfn(d, op.id, 1, &op.buf_pfn)) < 0 )
> + goto out;
> +
> + if ( (rc = hvm_get_ioreq_server_buf_port(d, op.id, &op.buf_port)) < 0 )
> + goto out;
> +
> + rc = copy_to_guest(uop, &op, 1) ? -EFAULT : 0;
> +
> +out:
> + rcu_unlock_domain(d);
> + return rc;
> +}
> +
> +static int hvmop_map_io_range_to_ioreq_server(
> + XEN_GUEST_HANDLE_PARAM(xen_hvm_map_io_range_to_ioreq_server_t) uop)
> +{
> + xen_hvm_map_io_range_to_ioreq_server_t op;
> + struct domain *d;
> + int rc;
> +
> + if ( copy_from_guest(&op, uop, 1) )
> + return -EFAULT;
> +
> + rc = rcu_lock_remote_domain_by_id(op.domid, &d);
> + if ( rc != 0 )
> + return rc;
> +
> + rc = -EINVAL;
> + if ( !is_hvm_domain(d) )
> + goto out;
> +
> + rc = hvm_map_io_range_to_ioreq_server(d, op.id, op.is_mmio,
> + op.start, op.end);
> +
> +out:
> + rcu_unlock_domain(d);
> + return rc;
> +}
> +
> +static int hvmop_unmap_io_range_from_ioreq_server(
> + XEN_GUEST_HANDLE_PARAM(xen_hvm_unmap_io_range_from_ioreq_server_t) uop)
> +{
> + xen_hvm_unmap_io_range_from_ioreq_server_t op;
> + struct domain *d;
> + int rc;
> +
> + if ( copy_from_guest(&op, uop, 1) )
> + return -EFAULT;
> +
> + rc = rcu_lock_remote_domain_by_id(op.domid, &d);
> + if ( rc != 0 )
> + return rc;
> +
> + rc = -EINVAL;
> + if ( !is_hvm_domain(d) )
> + goto out;
> +
> + rc = hvm_unmap_io_range_from_ioreq_server(d, op.id, op.is_mmio,
> + op.start);
> +
> +out:
> + rcu_unlock_domain(d);
> + return rc;
> +}
> +
> +static int hvmop_map_pcidev_to_ioreq_server(
> + XEN_GUEST_HANDLE_PARAM(xen_hvm_map_pcidev_to_ioreq_server_t) uop)
> +{
> + xen_hvm_map_pcidev_to_ioreq_server_t op;
> + struct domain *d;
> + int rc;
> +
> + if ( copy_from_guest(&op, uop, 1) )
> + return -EFAULT;
> +
> + rc = rcu_lock_remote_domain_by_id(op.domid, &d);
> + if ( rc != 0 )
> + return rc;
> +
> + rc = -EINVAL;
> + if ( !is_hvm_domain(d) )
> + goto out;
> +
> + rc = hvm_map_pcidev_to_ioreq_server(d, op.id, op.bdf);
> +
> +out:
> + rcu_unlock_domain(d);
> + return rc;
> +}
> +
> +static int hvmop_unmap_pcidev_from_ioreq_server(
> + XEN_GUEST_HANDLE_PARAM(xen_hvm_unmap_pcidev_from_ioreq_server_t) uop)
> +{
> + xen_hvm_unmap_pcidev_from_ioreq_server_t op;
> + struct domain *d;
> + int rc;
> +
> + if ( copy_from_guest(&op, uop, 1) )
> + return -EFAULT;
> +
> + rc = rcu_lock_remote_domain_by_id(op.domid, &d);
> + if ( rc != 0 )
> + return rc;
> +
> + rc = -EINVAL;
> + if ( !is_hvm_domain(d) )
> + goto out;
> +
> + rc = hvm_unmap_pcidev_from_ioreq_server(d, op.id, op.bdf);
> +
> +out:
> + rcu_unlock_domain(d);
> + return rc;
> +}
> +
> +static int hvmop_destroy_ioreq_server(
> + XEN_GUEST_HANDLE_PARAM(xen_hvm_destroy_ioreq_server_t) uop)
> +{
> + xen_hvm_destroy_ioreq_server_t op;
> + struct domain *d;
> + int rc;
> +
> + if ( copy_from_guest(&op, uop, 1) )
> + return -EFAULT;
> +
> + rc = rcu_lock_remote_domain_by_id(op.domid, &d);
> + if ( rc != 0 )
> + return rc;
> +
> + rc = -EINVAL;
> + if ( !is_hvm_domain(d) )
> + goto out;
> +
> + hvm_destroy_ioreq_server(d, op.id);
> + rc = 0;
> +
> +out:
> + rcu_unlock_domain(d);
> + return rc;
> +}
> +
> long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
>
> {
> @@ -4294,6 +5023,41 @@ long do_hvm_op(unsigned long op,
> XEN_GUEST_HANDLE_PARAM(void) arg)
>
> switch ( op )
> {
> + case HVMOP_create_ioreq_server:
> + rc = hvmop_create_ioreq_server(
> + guest_handle_cast(arg, xen_hvm_create_ioreq_server_t));
> + break;
> +
> + case HVMOP_get_ioreq_server_info:
> + rc = hvmop_get_ioreq_server_info(
> + guest_handle_cast(arg, xen_hvm_get_ioreq_server_info_t));
> + break;
> +
> + case HVMOP_map_io_range_to_ioreq_server:
> + rc = hvmop_map_io_range_to_ioreq_server(
> + guest_handle_cast(arg, xen_hvm_map_io_range_to_ioreq_server_t));
> + break;
> +
> + case HVMOP_unmap_io_range_from_ioreq_server:
> + rc = hvmop_unmap_io_range_from_ioreq_server(
> + guest_handle_cast(arg,
> xen_hvm_unmap_io_range_from_ioreq_server_t));
> + break;
> +
> + case HVMOP_map_pcidev_to_ioreq_server:
> + rc = hvmop_map_pcidev_to_ioreq_server(
> + guest_handle_cast(arg, xen_hvm_map_pcidev_to_ioreq_server_t));
> + break;
> +
> + case HVMOP_unmap_pcidev_from_ioreq_server:
> + rc = hvmop_unmap_pcidev_from_ioreq_server(
> + guest_handle_cast(arg,
> xen_hvm_unmap_pcidev_from_ioreq_server_t));
> + break;
> +
> + case HVMOP_destroy_ioreq_server:
> + rc = hvmop_destroy_ioreq_server(
> + guest_handle_cast(arg, xen_hvm_destroy_ioreq_server_t));
> + break;
> +
> case HVMOP_set_param:
> case HVMOP_get_param:
> {
> @@ -4382,9 +5146,9 @@ long do_hvm_op(unsigned long op,
> XEN_GUEST_HANDLE_PARAM(void) arg)
> if ( a.value == DOMID_SELF )
> a.value = curr_d->domain_id;
>
> - rc = hvm_create_ioreq_server(d, a.value);
> + rc = hvm_create_ioreq_server(d, 0, a.value);
> if ( rc == -EEXIST )
> - rc = hvm_set_ioreq_server_domid(d, a.value);
> + rc = hvm_set_ioreq_server_domid(d, 0, a.value);
> break;
> case HVM_PARAM_ACPI_S_STATE:
> /* Not reflexive, as we must domain_pause(). */
> @@ -4449,6 +5213,10 @@ long do_hvm_op(unsigned long op,
> XEN_GUEST_HANDLE_PARAM(void) arg)
> if ( a.value > SHUTDOWN_MAX )
> rc = -EINVAL;
> break;
> + case HVM_PARAM_NR_IOREQ_SERVERS:
> + if ( d == current->domain )
> + rc = -EPERM;
> + break;
Is this correct? Security-wise, it should be restricted more.
Having said that, I can't see anything good to come from being able to
change this value on the fly. Is it possible to make a domain creation
parameters?
> }
>
> if ( rc == 0 )
> @@ -4483,7 +5251,7 @@ long do_hvm_op(unsigned long op,
> XEN_GUEST_HANDLE_PARAM(void) arg)
> case HVM_PARAM_BUFIOREQ_PFN:
> case HVM_PARAM_BUFIOREQ_EVTCHN:
> /* May need to create server */
> - rc = hvm_create_ioreq_server(d, curr_d->domain_id);
> + rc = hvm_create_ioreq_server(d, 0, curr_d->domain_id);
> if ( rc != 0 && rc != -EEXIST )
> goto param_fail;
>
> @@ -4492,7 +5260,7 @@ long do_hvm_op(unsigned long op,
> XEN_GUEST_HANDLE_PARAM(void) arg)
> case HVM_PARAM_IOREQ_PFN: {
> xen_pfn_t pfn;
>
> - if ( (rc = hvm_get_ioreq_server_pfn(d, 0, &pfn)) < 0 )
> + if ( (rc = hvm_get_ioreq_server_pfn(d, 0, 0, &pfn)) < 0 )
> goto param_fail;
>
> a.value = pfn;
> @@ -4501,7 +5269,7 @@ long do_hvm_op(unsigned long op,
> XEN_GUEST_HANDLE_PARAM(void) arg)
> case HVM_PARAM_BUFIOREQ_PFN: {
> xen_pfn_t pfn;
>
> - if ( (rc = hvm_get_ioreq_server_pfn(d, 1, &pfn)) < 0 )
> + if ( (rc = hvm_get_ioreq_server_pfn(d, 0, 1, &pfn)) < 0 )
> goto param_fail;
>
> a.value = pfn;
> @@ -4510,7 +5278,7 @@ long do_hvm_op(unsigned long op,
> XEN_GUEST_HANDLE_PARAM(void) arg)
> case HVM_PARAM_BUFIOREQ_EVTCHN: {
> evtchn_port_t port;
>
> - if ( (rc = hvm_get_ioreq_server_buf_port(d, &port)) < 0 )
> + if ( (rc = hvm_get_ioreq_server_buf_port(d, 0, &port)) <
> 0 )
> goto param_fail;
>
> a.value = port;
> diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
> index 576641c..a0d76b2 100644
> --- a/xen/arch/x86/hvm/io.c
> +++ b/xen/arch/x86/hvm/io.c
> @@ -78,7 +78,7 @@ void send_invalidate_req(void)
> p->dir = IOREQ_WRITE;
> p->data = ~0UL; /* flush all */
>
> - (void)hvm_send_assist_req(v, p);
> + hvm_broadcast_assist_req(v, p);
> }
>
> int handle_mmio(void)
> diff --git a/xen/include/asm-x86/hvm/domain.h
> b/xen/include/asm-x86/hvm/domain.h
> index e750ef0..93dcec1 100644
> --- a/xen/include/asm-x86/hvm/domain.h
> +++ b/xen/include/asm-x86/hvm/domain.h
> @@ -41,19 +41,38 @@ struct hvm_ioreq_page {
> void *va;
> };
>
> +struct hvm_io_range {
> + struct hvm_io_range *next;
> + uint64_t start, end;
> +};
> +
> +struct hvm_pcidev {
> + struct hvm_pcidev *next;
> + uint16_t bdf;
> +};
> +
> struct hvm_ioreq_server {
> + struct list_head domain_list_entry;
> + struct list_head vcpu_list_entry[MAX_HVM_VCPUS];
Given that this has to be initialised anyway, would it be better to have
it dynamically sized on the d->max_cpus, which is almost always be far
smaller?
~Andrew
> + ioservid_t id;
> struct domain *domain;
> domid_t domid;
> struct hvm_ioreq_page ioreq;
> int ioreq_evtchn[MAX_HVM_VCPUS];
> struct hvm_ioreq_page buf_ioreq;
> int buf_ioreq_evtchn;
> + struct hvm_io_range *mmio_range_list;
> + struct hvm_io_range *portio_range_list;
> + struct hvm_pcidev *pcidev_list;
> };
>
> struct hvm_domain {
> - struct hvm_ioreq_server *ioreq_server;
> + struct list_head ioreq_server_list;
> spinlock_t ioreq_server_lock;
>
> + uint32_t pci_cf8;
> + spinlock_t pci_lock;
> +
> struct pl_time pl_time;
>
> struct hvm_io_handler *io_handler;
> diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
> index 4e8fee8..1c3854f 100644
> --- a/xen/include/asm-x86/hvm/hvm.h
> +++ b/xen/include/asm-x86/hvm/hvm.h
> @@ -225,6 +225,7 @@ int prepare_ring_for_helper(struct domain *d, unsigned
> long gmfn,
> void destroy_ring_for_helper(void **_va, struct page_info *page);
>
> bool_t hvm_send_assist_req(struct vcpu *v, ioreq_t *p);
> +void hvm_broadcast_assist_req(struct vcpu *v, ioreq_t *p);
>
> void hvm_get_guest_pat(struct vcpu *v, u64 *guest_pat);
> int hvm_set_guest_pat(struct vcpu *v, u64 guest_pat);
> diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h
> index 4c9d7ee..211ebfd 100644
> --- a/xen/include/asm-x86/hvm/vcpu.h
> +++ b/xen/include/asm-x86/hvm/vcpu.h
> @@ -138,7 +138,7 @@ struct hvm_vcpu {
> spinlock_t tm_lock;
> struct list_head tm_list;
>
> - struct hvm_ioreq_server *ioreq_server;
> + struct list_head ioreq_server_list;
>
> bool_t flag_dr_dirty;
> bool_t debug_state_latch;
> diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h
> index a9aab4b..6b31189 100644
> --- a/xen/include/public/hvm/hvm_op.h
> +++ b/xen/include/public/hvm/hvm_op.h
> @@ -23,6 +23,7 @@
>
> #include "../xen.h"
> #include "../trace.h"
> +#include "../event_channel.h"
>
> /* Get/set subcommands: extra argument == pointer to xen_hvm_param struct. */
> #define HVMOP_set_param 0
> @@ -270,6 +271,75 @@ struct xen_hvm_inject_msi {
> typedef struct xen_hvm_inject_msi xen_hvm_inject_msi_t;
> DEFINE_XEN_GUEST_HANDLE(xen_hvm_inject_msi_t);
>
> +typedef uint32_t ioservid_t;
> +
> +DEFINE_XEN_GUEST_HANDLE(ioservid_t);
> +
> +#define HVMOP_create_ioreq_server 17
> +struct xen_hvm_create_ioreq_server {
> + domid_t domid; /* IN - domain to be serviced */
> + ioservid_t id; /* OUT - server id */
> +};
> +typedef struct xen_hvm_create_ioreq_server xen_hvm_create_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_create_ioreq_server_t);
> +
> +#define HVMOP_get_ioreq_server_info 18
> +struct xen_hvm_get_ioreq_server_info {
> + domid_t domid; /* IN - domain to be serviced */
> + ioservid_t id; /* IN - server id */
> + xen_pfn_t pfn; /* OUT - ioreq pfn */
> + xen_pfn_t buf_pfn; /* OUT - buf ioreq pfn */
> + evtchn_port_t buf_port; /* OUT - buf ioreq port */
> +};
> +typedef struct xen_hvm_get_ioreq_server_info xen_hvm_get_ioreq_server_info_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_ioreq_server_info_t);
> +
> +#define HVMOP_map_io_range_to_ioreq_server 19
> +struct xen_hvm_map_io_range_to_ioreq_server {
> + domid_t domid; /* IN - domain to be serviced */
> + ioservid_t id; /* IN - handle from
> HVMOP_register_ioreq_server */
> + int is_mmio; /* IN - MMIO or port IO? */
> + uint64_aligned_t start, end; /* IN - inclusive start and end of range
> */
> +};
> +typedef struct xen_hvm_map_io_range_to_ioreq_server
> xen_hvm_map_io_range_to_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_map_io_range_to_ioreq_server_t);
> +
> +#define HVMOP_unmap_io_range_from_ioreq_server 20
> +struct xen_hvm_unmap_io_range_from_ioreq_server {
> + domid_t domid; /* IN - domain to be serviced */
> + ioservid_t id; /* IN - handle from HVMOP_register_ioreq_server
> */
> + uint8_t is_mmio; /* IN - MMIO or port IO? */
> + uint64_aligned_t start; /* IN - start address of the range to remove */
> +};
> +typedef struct xen_hvm_unmap_io_range_from_ioreq_server
> xen_hvm_unmap_io_range_from_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_unmap_io_range_from_ioreq_server_t);
> +
> +#define HVMOP_map_pcidev_to_ioreq_server 21
> +struct xen_hvm_map_pcidev_to_ioreq_server {
> + domid_t domid; /* IN - domain to be serviced */
> + ioservid_t id; /* IN - handle from HVMOP_register_ioreq_server */
> + uint16_t bdf; /* IN - PCI bus/dev/func */
> +};
> +typedef struct xen_hvm_map_pcidev_to_ioreq_server
> xen_hvm_map_pcidev_to_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_map_pcidev_to_ioreq_server_t);
> +
> +#define HVMOP_unmap_pcidev_from_ioreq_server 22
> +struct xen_hvm_unmap_pcidev_from_ioreq_server {
> + domid_t domid; /* IN - domain to be serviced */
> + ioservid_t id; /* IN - handle from HVMOP_register_ioreq_server */
> + uint16_t bdf; /* IN - PCI bus/dev/func */
> +};
> +typedef struct xen_hvm_unmap_pcidev_from_ioreq_server
> xen_hvm_unmap_pcidev_from_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_unmap_pcidev_from_ioreq_server_t);
> +
> +#define HVMOP_destroy_ioreq_server 23
> +struct xen_hvm_destroy_ioreq_server {
> + domid_t domid; /* IN - domain to be serviced */
> + ioservid_t id; /* IN - server id */
> +};
> +typedef struct xen_hvm_destroy_ioreq_server xen_hvm_destroy_ioreq_server_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_destroy_ioreq_server_t);
> +
> #endif /* defined(__XEN__) || defined(__XEN_TOOLS__) */
>
> #endif /* __XEN_PUBLIC_HVM_HVM_OP_H__ */
> diff --git a/xen/include/public/hvm/ioreq.h b/xen/include/public/hvm/ioreq.h
> index f05d130..e84fa75 100644
> --- a/xen/include/public/hvm/ioreq.h
> +++ b/xen/include/public/hvm/ioreq.h
> @@ -34,6 +34,7 @@
>
> #define IOREQ_TYPE_PIO 0 /* pio */
> #define IOREQ_TYPE_COPY 1 /* mmio ops */
> +#define IOREQ_TYPE_PCI_CONFIG 2 /* pci config ops */
> #define IOREQ_TYPE_TIMEOFFSET 7
> #define IOREQ_TYPE_INVALIDATE 8 /* mapcache */
>
> diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h
> index 517a184..4109b11 100644
> --- a/xen/include/public/hvm/params.h
> +++ b/xen/include/public/hvm/params.h
> @@ -145,6 +145,8 @@
> /* SHUTDOWN_* action in case of a triple fault */
> #define HVM_PARAM_TRIPLE_FAULT_REASON 31
>
> -#define HVM_NR_PARAMS 32
> +#define HVM_PARAM_NR_IOREQ_SERVERS 32
> +
> +#define HVM_NR_PARAMS 33
>
> #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |