|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [RFC PATCH 5/5] ioreq-server: bring the PCI hotplug controller implementation into Xen
On 30/01/14 14:19, Paul Durrant wrote:
> Because we may now have more than one emulator, the implementation of the
> PCI hotplug controller needs to be done by Xen. Happily the code is very
> short and simple and it also removes the need for a different ACPI DSDT
> when using different variants of QEMU.
>
> Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
> ---
> tools/firmware/hvmloader/acpi/mk_dsdt.c | 147 ++++------------------
> tools/libxc/xc_domain.c | 46 +++++++
> tools/libxc/xenctrl.h | 11 ++
> tools/libxl/libxl_pci.c | 15 +++
> xen/arch/x86/hvm/Makefile | 1 +
> xen/arch/x86/hvm/hotplug.c | 207
> +++++++++++++++++++++++++++++++
> xen/arch/x86/hvm/hvm.c | 40 +++++-
> xen/include/asm-x86/hvm/domain.h | 12 ++
> xen/include/asm-x86/hvm/io.h | 6 +
> xen/include/public/hvm/hvm_op.h | 9 ++
> xen/include/public/hvm/ioreq.h | 2 +
> 11 files changed, 373 insertions(+), 123 deletions(-)
> create mode 100644 xen/arch/x86/hvm/hotplug.c
>
> diff --git a/tools/firmware/hvmloader/acpi/mk_dsdt.c
> b/tools/firmware/hvmloader/acpi/mk_dsdt.c
> index a4b693b..6408b44 100644
> --- a/tools/firmware/hvmloader/acpi/mk_dsdt.c
> +++ b/tools/firmware/hvmloader/acpi/mk_dsdt.c
> @@ -58,28 +58,6 @@ static void pop_block(void)
> printf("}\n");
> }
>
> -static void pci_hotplug_notify(unsigned int slt)
> -{
> - stmt("Notify", "\\_SB.PCI0.S%02X, EVT", slt);
> -}
> -
> -static void decision_tree(
> - unsigned int s, unsigned int e, char *var, void (*leaf)(unsigned int))
> -{
> - if ( s == (e-1) )
> - {
> - (*leaf)(s);
> - return;
> - }
> -
> - push_block("If", "And(%s, 0x%02x)", var, (e-s)/2);
> - decision_tree((s+e)/2, e, var, leaf);
> - pop_block();
> - push_block("Else", NULL);
> - decision_tree(s, (s+e)/2, var, leaf);
> - pop_block();
> -}
> -
> static struct option options[] = {
> { "maxcpu", 1, 0, 'c' },
> { "dm-version", 1, 0, 'q' },
> @@ -322,64 +300,21 @@ int main(int argc, char **argv)
> dev, intx, ((dev*4+dev/8+intx)&31)+16);
> printf("})\n");
>
> - /*
> - * Each PCI hotplug slot needs at least two methods to handle
> - * the ACPI event:
> - * _EJ0: eject a device
> - * _STA: return a device's status, e.g. enabled or removed
> - *
> - * Eject button would generate a general-purpose event, then the
> - * control method for this event uses Notify() to inform OSPM which
> - * action happened and on which device.
> - *
> - * Pls. refer "6.3 Device Insertion, Removal, and Status Objects"
> - * in ACPI spec 3.0b for details.
> - *
> - * QEMU provides a simple hotplug controller with some I/O to handle
> - * the hotplug action and status, which is beyond the ACPI scope.
> - */
> - if (dm_version == QEMU_XEN_TRADITIONAL) {
> - for ( slot = 0; slot < 0x100; slot++ )
> - {
> - push_block("Device", "S%02X", slot);
> - /* _ADR == dev:fn (16:16) */
> - stmt("Name", "_ADR, 0x%08x", ((slot & ~7) << 13) | (slot & 7));
> - /* _SUN == dev */
> - stmt("Name", "_SUN, 0x%08x", slot >> 3);
> - push_block("Method", "_EJ0, 1");
> - stmt("Store", "0x%02x, \\_GPE.DPT1", slot);
> - stmt("Store", "0x88, \\_GPE.DPT2");
> - stmt("Store", "0x%02x, \\_GPE.PH%02X", /* eject */
> - (slot & 1) ? 0x10 : 0x01, slot & ~1);
> - pop_block();
> - push_block("Method", "_STA, 0");
> - stmt("Store", "0x%02x, \\_GPE.DPT1", slot);
> - stmt("Store", "0x89, \\_GPE.DPT2");
> - if ( slot & 1 )
> - stmt("ShiftRight", "0x4, \\_GPE.PH%02X, Local1", slot & ~1);
> - else
> - stmt("And", "\\_GPE.PH%02X, 0x0f, Local1", slot & ~1);
> - stmt("Return", "Local1"); /* IN status as the _STA */
> - pop_block();
> - pop_block();
> - }
> - } else {
> - stmt("OperationRegion", "SEJ, SystemIO, 0xae08, 0x04");
> - push_block("Field", "SEJ, DWordAcc, NoLock, WriteAsZeros");
> - indent(); printf("B0EJ, 32,\n");
> - pop_block();
> + stmt("OperationRegion", "SEJ, SystemIO, 0xae08, 0x04");
> + push_block("Field", "SEJ, DWordAcc, NoLock, WriteAsZeros");
> + indent(); printf("B0EJ, 32,\n");
> + pop_block();
>
> - /* hotplug_slot */
> - for (slot = 1; slot <= 31; slot++) {
> - push_block("Device", "S%i", slot); {
> - stmt("Name", "_ADR, %#06x0000", slot);
> - push_block("Method", "_EJ0,1"); {
> - stmt("Store", "ShiftLeft(1, %#06x), B0EJ", slot);
> - stmt("Return", "0x0");
> - } pop_block();
> - stmt("Name", "_SUN, %i", slot);
> + /* hotplug_slot */
> + for (slot = 1; slot <= 31; slot++) {
> + push_block("Device", "S%i", slot); {
> + stmt("Name", "_ADR, %#06x0000", slot);
> + push_block("Method", "_EJ0,1"); {
> + stmt("Store", "ShiftLeft(1, %#06x), B0EJ", slot);
> + stmt("Return", "0x0");
> } pop_block();
> - }
> + stmt("Name", "_SUN, %i", slot);
> + } pop_block();
> }
>
> pop_block();
> @@ -389,26 +324,11 @@ int main(int argc, char **argv)
> /**** GPE start ****/
> push_block("Scope", "\\_GPE");
>
> - if (dm_version == QEMU_XEN_TRADITIONAL) {
> - stmt("OperationRegion", "PHP, SystemIO, 0x10c0, 0x82");
> -
> - push_block("Field", "PHP, ByteAcc, NoLock, Preserve");
> - indent(); printf("PSTA, 8,\n"); /* hotplug controller event reg */
> - indent(); printf("PSTB, 8,\n"); /* hotplug controller slot reg */
> - for ( slot = 0; slot < 0x100; slot += 2 )
> - {
> - indent();
> - /* Each hotplug control register manages a pair of pci
> functions. */
> - printf("PH%02X, 8,\n", slot);
> - }
> - pop_block();
> - } else {
> - stmt("OperationRegion", "PCST, SystemIO, 0xae00, 0x08");
> - push_block("Field", "PCST, DWordAcc, NoLock, WriteAsZeros");
> - indent(); printf("PCIU, 32,\n");
> - indent(); printf("PCID, 32,\n");
> - pop_block();
> - }
> + stmt("OperationRegion", "PCST, SystemIO, 0xae00, 0x08");
> + push_block("Field", "PCST, DWordAcc, NoLock, WriteAsZeros");
> + indent(); printf("PCIU, 32,\n");
> + indent(); printf("PCID, 32,\n");
> + pop_block();
>
> stmt("OperationRegion", "DG1, SystemIO, 0xb044, 0x04");
>
> @@ -416,33 +336,16 @@ int main(int argc, char **argv)
> indent(); printf("DPT1, 8, DPT2, 8\n");
> pop_block();
>
> - if (dm_version == QEMU_XEN_TRADITIONAL) {
> - push_block("Method", "_L03, 0, Serialized");
> - /* Detect slot and event (remove/add). */
> - stmt("Name", "SLT, 0x0");
> - stmt("Name", "EVT, 0x0");
> - stmt("Store", "PSTA, Local1");
> - stmt("And", "Local1, 0xf, EVT");
> - stmt("Store", "PSTB, Local1"); /* XXX: Store (PSTB, SLT) ? */
> - stmt("And", "Local1, 0xff, SLT");
> - /* Debug */
> - stmt("Store", "SLT, DPT1");
> - stmt("Store", "EVT, DPT2");
> - /* Decision tree */
> - decision_tree(0x00, 0x100, "SLT", pci_hotplug_notify);
> + push_block("Method", "_E01");
> + for (slot = 1; slot <= 31; slot++) {
> + push_block("If", "And(PCIU, ShiftLeft(1, %i))", slot);
> + stmt("Notify", "\\_SB.PCI0.S%i, 1", slot);
> pop_block();
> - } else {
> - push_block("Method", "_E01");
> - for (slot = 1; slot <= 31; slot++) {
> - push_block("If", "And(PCIU, ShiftLeft(1, %i))", slot);
> - stmt("Notify", "\\_SB.PCI0.S%i, 1", slot);
> - pop_block();
> - push_block("If", "And(PCID, ShiftLeft(1, %i))", slot);
> - stmt("Notify", "\\_SB.PCI0.S%i, 3", slot);
> - pop_block();
> - }
> + push_block("If", "And(PCID, ShiftLeft(1, %i))", slot);
> + stmt("Notify", "\\_SB.PCI0.S%i, 3", slot);
> pop_block();
> }
> + pop_block();
>
> pop_block();
> /**** GPE end ****/
> diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
> index c64d15a..c89068e 100644
> --- a/tools/libxc/xc_domain.c
> +++ b/tools/libxc/xc_domain.c
> @@ -1421,6 +1421,52 @@ int xc_hvm_destroy_ioreq_server(xc_interface *xch,
> return rc;
> }
>
> +int xc_hvm_pci_hotplug_enable(xc_interface *xch,
> + domid_t domid,
> + uint32_t slot)
Take enable as a parameter and save having 2 almost identical functions?
> +{
> + DECLARE_HYPERCALL;
> + DECLARE_HYPERCALL_BUFFER(xen_hvm_pci_hotplug_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_pci_hotplug;
> + hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
> + arg->domid = domid;
> + arg->enable = 1;
> + arg->slot = slot;
> + rc = do_xen_hypercall(xch, &hypercall);
> + xc_hypercall_buffer_free(xch, arg);
> + return rc;
> +}
> +
> +int xc_hvm_pci_hotplug_disable(xc_interface *xch,
> + domid_t domid,
> + uint32_t slot)
> +{
> + DECLARE_HYPERCALL;
> + DECLARE_HYPERCALL_BUFFER(xen_hvm_pci_hotplug_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_pci_hotplug;
> + hypercall.arg[1] = HYPERCALL_BUFFER_AS_ARG(arg);
> + arg->domid = domid;
> + arg->enable = 0;
> + arg->slot = slot;
> + 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/xenctrl.h b/tools/libxc/xenctrl.h
> index 142aaea..c3e35a9 100644
> --- a/tools/libxc/xenctrl.h
> +++ b/tools/libxc/xenctrl.h
> @@ -1842,6 +1842,17 @@ int xc_hvm_destroy_ioreq_server(xc_interface *xch,
> domid_t domid,
> ioservid_t id);
>
> +/*
> + * PCI hotplug API
> + */
> +int xc_hvm_pci_hotplug_enable(xc_interface *xch,
> + domid_t domid,
> + uint32_t slot);
> +
> +int xc_hvm_pci_hotplug_disable(xc_interface *xch,
> + domid_t domid,
> + uint32_t slot);
> +
tabs/spaces
> /* HVM guest pass-through */
> int xc_assign_device(xc_interface *xch,
> uint32_t domid,
> diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c
> index 2e52470..4176440 100644
> --- a/tools/libxl/libxl_pci.c
> +++ b/tools/libxl/libxl_pci.c
> @@ -867,6 +867,13 @@ static int do_pci_add(libxl__gc *gc, uint32_t domid,
> libxl_device_pci *pcidev, i
> }
> if ( rc )
> return ERROR_FAIL;
> +
> + rc = xc_hvm_pci_hotplug_enable(ctx->xch, domid, pcidev->dev);
> + if (rc < 0) {
> + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Error:
> xc_hvm_pci_hotplug_enable failed");
> + return ERROR_FAIL;
> + }
> +
> break;
> case LIBXL_DOMAIN_TYPE_PV:
> {
> @@ -1182,6 +1189,14 @@ static int do_pci_remove(libxl__gc *gc, uint32_t domid,
> NULL, NULL, NULL) < 0)
> goto out_fail;
>
> + rc = xc_hvm_pci_hotplug_disable(ctx->xch, domid, pcidev->dev);
> + if (rc < 0) {
> + LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
> + "Error: xc_hvm_pci_hotplug_disable failed");
> + rc = ERROR_FAIL;
> + goto out_fail;
> + }
> +
> switch (libxl__device_model_version_running(gc, domid)) {
> case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
> rc = qemu_pci_remove_xenstore(gc, domid, pcidev, force);
> diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
> index eea5555..48efddb 100644
> --- a/xen/arch/x86/hvm/Makefile
> +++ b/xen/arch/x86/hvm/Makefile
> @@ -3,6 +3,7 @@ subdir-y += vmx
>
> obj-y += asid.o
> obj-y += emulate.o
> +obj-y += hotplug.o
> obj-y += hpet.o
> obj-y += hvm.o
> obj-y += i8254.o
> diff --git a/xen/arch/x86/hvm/hotplug.c b/xen/arch/x86/hvm/hotplug.c
> new file mode 100644
> index 0000000..253d435
> --- /dev/null
> +++ b/xen/arch/x86/hvm/hotplug.c
> @@ -0,0 +1,207 @@
> +/*
> + * hvm/hotplug.c
> + *
> + * Copyright (c) 2013, Citrix Systems Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> with
> + * this program; if not, write to the Free Software Foundation, Inc., 59
> Temple
> + * Place - Suite 330, Boston, MA 02111-1307 USA.
> + */
> +
> +#include <xen/types.h>
> +#include <xen/spinlock.h>
> +#include <xen/xmalloc.h>
> +#include <asm/hvm/io.h>
> +#include <asm/hvm/support.h>
> +
> +#define SCI_IRQ 9
> +
> +#define GPE_BASE (ACPI_GPE0_BLK_ADDRESS_V1)
> +#define GPE_LEN (ACPI_GPE0_BLK_LEN_V1)
> +
> +#define GPE_PCI_HOTPLUG_STATUS 2
> +
> +#define PCI_HOTPLUG_BASE (ACPI_PCI_HOTPLUG_ADDRESS_V1)
> +#define PCI_HOTPLUG_LEN (ACPI_PCI_HOTPLUG_LEN_V1)
> +
> +#define PCI_UP 0
> +#define PCI_DOWN 4
> +#define PCI_EJECT 8
> +
> +static void gpe_update_sci(struct hvm_hotplug *hp)
> +{
> + if ( (hp->gpe_sts[0] & hp->gpe_en[0]) & GPE_PCI_HOTPLUG_STATUS )
> + hvm_isa_irq_assert(hp->domain, SCI_IRQ);
> + else
> + hvm_isa_irq_deassert(hp->domain, SCI_IRQ);
> +}
> +
> +static int handle_gpe_io(
> + int dir, uint32_t port, uint32_t bytes, uint32_t *val)
> +{
> + struct vcpu *v = current;
> + struct domain *d = v->domain;
> + struct hvm_hotplug *hp = &d->arch.hvm_domain.hotplug;
> +
> + if ( bytes != 1 )
> + {
> + gdprintk(XENLOG_WARNING, "%s: bad access\n", __func__);
> + goto done;
> + }
> +
> + port -= GPE_BASE;
> +
> + if ( dir == IOREQ_READ )
> + {
> + if ( port < GPE_LEN / 2 )
> + {
> + *val = hp->gpe_sts[port];
> + }
> + else
> + {
> + port -= GPE_LEN / 2;
> + *val = hp->gpe_en[port];
> + }
> + } else {
> + if ( port < GPE_LEN / 2 )
> + {
> + hp->gpe_sts[port] &= ~*val;
> + }
> + else
> + {
> + port -= GPE_LEN / 2;
> + hp->gpe_en[port] = *val;
> + }
> +
> + gpe_update_sci(hp);
> + }
> +
> +done:
> + return X86EMUL_OKAY;
> +}
> +
> +static void pci_hotplug_eject(struct hvm_hotplug *hp, uint32_t mask)
> +{
> + int slot = ffs(mask) - 1;
> +
> + gdprintk(XENLOG_INFO, "%s: %d\n", __func__, slot);
> +
> + hp->slot_down &= ~(1u << slot);
> + hp->slot_up &= ~(1u << slot);
> +}
> +
> +static int handle_pci_hotplug_io(
> + int dir, uint32_t port, uint32_t bytes, uint32_t *val)
> +{
> + struct vcpu *v = current;
> + struct domain *d = v->domain;
> + struct hvm_hotplug *hp = &d->arch.hvm_domain.hotplug;
> +
> + if ( bytes != 4 )
> + {
> + gdprintk(XENLOG_WARNING, "%s: bad access\n", __func__);
> + goto done;
> + }
> +
> + port -= PCI_HOTPLUG_BASE;
> +
> + if ( dir == IOREQ_READ )
> + {
> + switch ( port )
> + {
> + case PCI_UP:
> + *val = hp->slot_up;
> + break;
> + case PCI_DOWN:
> + *val = hp->slot_down;
> + break;
> + default:
> + break;
> + }
> + }
> + else
> + {
> + switch ( port )
> + {
> + case PCI_EJECT:
> + pci_hotplug_eject(hp, *val);
> + break;
> + default:
> + break;
> + }
> + }
> +
> +done:
> + return X86EMUL_OKAY;
> +}
> +
> +void pci_hotplug(struct domain *d, int slot, bool_t enable)
> +{
> + struct hvm_hotplug *hp = &d->arch.hvm_domain.hotplug;
> +
> + gdprintk(XENLOG_INFO, "%s: %s %d\n", __func__,
> + ( enable ) ? "enable" : "disable", slot);
> +
> + if ( enable )
> + hp->slot_up |= (1u << slot);
> + else
> + hp->slot_down |= (1u << slot);
> +
> + hp->gpe_sts[0] |= GPE_PCI_HOTPLUG_STATUS;
> + gpe_update_sci(hp);
> +}
> +
> +int gpe_init(struct domain *d)
> +{
> + struct hvm_hotplug *hp = &d->arch.hvm_domain.hotplug;
> +
> + hp->domain = d;
> +
> + hp->gpe_sts = xzalloc_array(uint8_t, GPE_LEN / 2);
This size is known at compile time - what about arrays inside
hvm_hotplug and forgo the small memory allocations?
> + if ( hp->gpe_sts == NULL )
> + goto fail1;
> +
> + hp->gpe_en = xzalloc_array(uint8_t, GPE_LEN / 2);
> + if ( hp->gpe_en == NULL )
> + goto fail2;
> +
> + register_portio_handler(d, GPE_BASE, GPE_LEN, handle_gpe_io);
> + register_portio_handler(d, PCI_HOTPLUG_BASE, PCI_HOTPLUG_LEN,
> + handle_pci_hotplug_io);
> +
> + return 0;
> +
> +fail2:
> + xfree(hp->gpe_sts);
> +
> +fail1:
> + return -ENOMEM;
> +}
> +
> +void gpe_deinit(struct domain *d)
> +{
> + struct hvm_hotplug *hp = &d->arch.hvm_domain.hotplug;
> +
> + xfree(hp->gpe_en);
> + xfree(hp->gpe_sts);
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * c-tab-always-indent: nil
> + * End:
> + */
> diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
> index 5f9e728..ff7b259 100644
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -1298,15 +1298,21 @@ int hvm_domain_initialise(struct domain *d)
>
> rtc_init(d);
>
> + rc = gpe_init(d);
> + if ( rc != 0 )
> + goto fail2;
> +
> 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 )
> - goto fail2;
> + goto fail3;
>
> return 0;
>
> + fail3:
> + gpe_deinit(d);
> fail2:
> rtc_deinit(d);
> stdvga_deinit(d);
> @@ -1352,6 +1358,7 @@ void hvm_domain_destroy(struct domain *d)
> return;
>
> hvm_funcs.domain_destroy(d);
> + gpe_deinit(d);
> rtc_deinit(d);
> stdvga_deinit(d);
> vioapic_deinit(d);
> @@ -5015,6 +5022,32 @@ out:
> return rc;
> }
>
> +static int hvmop_pci_hotplug(
> + XEN_GUEST_HANDLE_PARAM(xen_hvm_pci_hotplug_t) uop)
> +{
> + xen_hvm_pci_hotplug_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;
> +
> + pci_hotplug(d, op.slot, op.enable);
> + rc = 0;
> +
> +out:
> + rcu_unlock_domain(d);
> + return rc;
> +}
> +
> long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
>
> {
> @@ -5058,6 +5091,11 @@ long do_hvm_op(unsigned long op,
> XEN_GUEST_HANDLE_PARAM(void) arg)
> guest_handle_cast(arg, xen_hvm_destroy_ioreq_server_t));
> break;
>
> + case HVMOP_pci_hotplug:
> + rc = hvmop_pci_hotplug(
> + guest_handle_cast(arg, xen_hvm_pci_hotplug_t));
> + break;
> +
> case HVMOP_set_param:
> case HVMOP_get_param:
> {
> diff --git a/xen/include/asm-x86/hvm/domain.h
> b/xen/include/asm-x86/hvm/domain.h
> index 93dcec1..13dd24d 100644
> --- a/xen/include/asm-x86/hvm/domain.h
> +++ b/xen/include/asm-x86/hvm/domain.h
> @@ -66,6 +66,16 @@ struct hvm_ioreq_server {
> struct hvm_pcidev *pcidev_list;
> };
>
> +struct hvm_hotplug {
> + struct domain *domain;
This appears to be found by using container_of(), which will help keep
the size of struct domain down.
> + uint8_t *gpe_sts;
> + uint8_t *gpe_en;
> +
> + /* PCI hotplug */
> + uint32_t slot_up;
> + uint32_t slot_down;
> +};
> +
> struct hvm_domain {
> struct list_head ioreq_server_list;
> spinlock_t ioreq_server_lock;
> @@ -73,6 +83,8 @@ struct hvm_domain {
> uint32_t pci_cf8;
> spinlock_t pci_lock;
>
> + struct hvm_hotplug hotplug;
> +
> struct pl_time pl_time;
>
> struct hvm_io_handler *io_handler;
> diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h
> index 86db58d..072bfe7 100644
> --- a/xen/include/asm-x86/hvm/io.h
> +++ b/xen/include/asm-x86/hvm/io.h
> @@ -142,5 +142,11 @@ void stdvga_init(struct domain *d);
> void stdvga_deinit(struct domain *d);
>
> extern void hvm_dpci_msi_eoi(struct domain *d, int vector);
> +
> +int gpe_init(struct domain *d);
> +void gpe_deinit(struct domain *d);
> +
> +void pci_hotplug(struct domain *d, int slot, bool_t enable);
> +
> #endif /* __ASM_X86_HVM_IO_H__ */
>
> diff --git a/xen/include/public/hvm/hvm_op.h b/xen/include/public/hvm/hvm_op.h
> index 6b31189..20a53ab 100644
> --- a/xen/include/public/hvm/hvm_op.h
> +++ b/xen/include/public/hvm/hvm_op.h
> @@ -340,6 +340,15 @@ struct xen_hvm_destroy_ioreq_server {
> typedef struct xen_hvm_destroy_ioreq_server xen_hvm_destroy_ioreq_server_t;
> DEFINE_XEN_GUEST_HANDLE(xen_hvm_destroy_ioreq_server_t);
>
> +#define HVMOP_pci_hotplug 24
> +struct xen_hvm_pci_hotplug {
> + domid_t domid; /* IN - domain to be serviced */
> + uint8_t enable; /* IN - enable or disable? */
> + uint32_t slot; /* IN - slot to enable/disable */
Reordering these two will make the structure smaller.
~Andrew
> +};
> +typedef struct xen_hvm_pci_hotplug xen_hvm_pci_hotplug_t;
> +DEFINE_XEN_GUEST_HANDLE(xen_hvm_pci_hotplug_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 e84fa75..40bfa61 100644
> --- a/xen/include/public/hvm/ioreq.h
> +++ b/xen/include/public/hvm/ioreq.h
> @@ -101,6 +101,8 @@ typedef struct buffered_iopage buffered_iopage_t;
> #define ACPI_PM_TMR_BLK_ADDRESS_V1 (ACPI_PM1A_EVT_BLK_ADDRESS_V1 + 0x08)
> #define ACPI_GPE0_BLK_ADDRESS_V1 0xafe0
> #define ACPI_GPE0_BLK_LEN_V1 0x04
> +#define ACPI_PCI_HOTPLUG_ADDRESS_V1 0xae00
> +#define ACPI_PCI_HOTPLUG_LEN_V1 0x10
>
> /* Compatibility definitions for the default location (version 0). */
> #define ACPI_PM1A_EVT_BLK_ADDRESS ACPI_PM1A_EVT_BLK_ADDRESS_V0
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |