[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 |