[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v4 7/9] vpci/msi: add MSI handlers
> -----Original Message----- > From: Roger Pau Monne [mailto:roger.pau@xxxxxxxxxx] > Sent: 30 June 2017 16:01 > To: xen-devel@xxxxxxxxxxxxxxxxxxxx > Cc: boris.ostrovsky@xxxxxxxxxx; julien.grall@xxxxxxx; > konrad.wilk@xxxxxxxxxx; Roger Pau Monne <roger.pau@xxxxxxxxxx>; Jan > Beulich <jbeulich@xxxxxxxx>; Andrew Cooper > <Andrew.Cooper3@xxxxxxxxxx>; Paul Durrant <Paul.Durrant@xxxxxxxxxx> > Subject: [PATCH v4 7/9] vpci/msi: add MSI handlers > > Add handlers for the MSI control, address, data and mask fields in > order to detect accesses to them and setup the interrupts as requested > by the guest. > > Note that the pending register is not trapped, and the guest can > freely read/write to it. > > Whether Xen is going to provide this functionality to Dom0 (MSI > emulation) is controlled by the "msi" option in the dom0 field. When > disabling this option Xen will hide the MSI capability structure from > Dom0. > > Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> > --- > Cc: Jan Beulich <jbeulich@xxxxxxxx> > Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> > Cc: Paul Durrant <paul.durrant@xxxxxxxxxx> > --- > Changes since v3: > - Propagate changes from previous versions: drop xen_ prefix, drop > return value from handlers, use the new vpci_val fields. > - Use MASK_EXTR. > - Remove the usage of GENMASK. > - Add GFLAGS_SHIFT_DEST_ID and use it in msi_flags. > - Add "arch" to the MSI arch specific functions. > - Move the dumping of vPCI MSI information to dump_msi (key 'M'). > - Remove the guest_vectors field. > - Allow the guest to change the number of active vectors without > having to disable and enable MSI. > - Check the number of active vectors when parsing the disable > mask. > - Remove the debug messages from vpci_init_msi. > - Move the arch-specific part of the dump handler to x86/hvm/vmsi.c. > - Use trylock in the dump handler to get the vpci lock. > > Changes since v2: > - Add an arch-specific abstraction layer. Note that this is only implemented > for x86 currently. > - Add a wrapper to detect MSI enabling for vPCI. > > NB: I've only been able to test this with devices using a single MSI interrupt > and no mask register. I will try to find hardware that supports the mask > register and more than one vector, but I cannot make any promises. > > If there are doubts about the untested parts we could always force Xen to > report no per-vector masking support and only 1 available vector, but I would > rather avoid doing it. > --- > xen/arch/x86/hvm/vmsi.c | 149 ++++++++++++++++++ > xen/arch/x86/msi.c | 3 + > xen/drivers/vpci/Makefile | 2 +- > xen/drivers/vpci/msi.c | 348 > +++++++++++++++++++++++++++++++++++++++++++ > xen/include/asm-x86/hvm/io.h | 18 +++ > xen/include/asm-x86/msi.h | 1 + > xen/include/xen/hvm/irq.h | 2 + > xen/include/xen/vpci.h | 26 ++++ > 8 files changed, 548 insertions(+), 1 deletion(-) > create mode 100644 xen/drivers/vpci/msi.c > > diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c > index a36692c313..5732c70b5c 100644 > --- a/xen/arch/x86/hvm/vmsi.c > +++ b/xen/arch/x86/hvm/vmsi.c > @@ -622,3 +622,152 @@ void msix_write_completion(struct vcpu *v) > if ( msixtbl_write(v, ctrl_address, 4, 0) != X86EMUL_OKAY ) > gdprintk(XENLOG_WARNING, "MSI-X write completion failure\n"); > } > + > +static unsigned int msi_vector(uint16_t data) > +{ > + return MASK_EXTR(data, MSI_DATA_VECTOR_MASK); > +} > + > +static unsigned int msi_flags(uint16_t data, uint64_t addr) > +{ > + unsigned int rh, dm, dest_id, deliv_mode, trig_mode; > + > + rh = MASK_EXTR(addr, MSI_ADDR_REDIRECTION_MASK); > + dm = MASK_EXTR(addr, MSI_ADDR_DESTMODE_MASK); > + dest_id = MASK_EXTR(addr, MSI_ADDR_DEST_ID_MASK); > + deliv_mode = MASK_EXTR(data, MSI_DATA_DELIVERY_MODE_MASK); > + trig_mode = MASK_EXTR(data, MSI_DATA_TRIGGER_MASK); > + > + return (dest_id << GFLAGS_SHIFT_DEST_ID) | (rh << GFLAGS_SHIFT_RH) > | > + (dm << GFLAGS_SHIFT_DM) | (deliv_mode << > GFLAGS_SHIFT_DELIV_MODE) | > + (trig_mode << GFLAGS_SHIFT_TRG_MODE); > +} > + > +void vpci_msi_arch_mask(struct vpci_arch_msi *arch, struct pci_dev *pdev, > + unsigned int entry, bool mask) > +{ > + struct domain *d = pdev->domain; > + const struct pirq *pinfo; > + struct irq_desc *desc; > + unsigned long flags; > + int irq; > + > + ASSERT(arch->pirq >= 0); > + pinfo = pirq_info(d, arch->pirq + entry); > + ASSERT(pinfo); > + > + irq = pinfo->arch.irq; > + ASSERT(irq < nr_irqs && irq >= 0); > + > + desc = irq_to_desc(irq); > + ASSERT(desc); > + > + spin_lock_irqsave(&desc->lock, flags); > + guest_mask_msi_irq(desc, mask); > + spin_unlock_irqrestore(&desc->lock, flags); > +} > + > +int vpci_msi_arch_enable(struct vpci_arch_msi *arch, struct pci_dev *pdev, > + uint64_t address, uint32_t data, unsigned int > vectors) > +{ > + struct msi_info msi_info = { > + .seg = pdev->seg, > + .bus = pdev->bus, > + .devfn = pdev->devfn, > + .entry_nr = vectors, > + }; > + unsigned int i; > + int rc; > + > + ASSERT(arch->pirq == -1); > + > + /* Get a PIRQ. */ > + rc = allocate_and_map_msi_pirq(pdev->domain, -1, &arch->pirq, > + MAP_PIRQ_TYPE_MULTI_MSI, &msi_info); > + if ( rc ) > + { > + dprintk(XENLOG_ERR, "%04x:%02x:%02x.%u: failed to map PIRQ: > %d\n", > + pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn), > + PCI_FUNC(pdev->devfn), rc); > + return rc; > + } > + > + for ( i = 0; i < vectors; i++ ) > + { > + xen_domctl_bind_pt_irq_t bind = { > + .machine_irq = arch->pirq + i, > + .irq_type = PT_IRQ_TYPE_MSI, > + .u.msi.gvec = msi_vector(data) + i, > + .u.msi.gflags = msi_flags(data, address), > + }; > + > + pcidevs_lock(); > + rc = pt_irq_create_bind(pdev->domain, &bind); > + if ( rc ) > + { > + dprintk(XENLOG_ERR, > + "%04x:%02x:%02x.%u: failed to bind PIRQ %u: %d\n", > + pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn), > + PCI_FUNC(pdev->devfn), arch->pirq + i, rc); > + spin_lock(&pdev->domain->event_lock); > + unmap_domain_pirq(pdev->domain, arch->pirq); > + spin_unlock(&pdev->domain->event_lock); > + pcidevs_unlock(); > + arch->pirq = -1; > + return rc; > + } > + pcidevs_unlock(); > + } > + > + return 0; > +} > + > +int vpci_msi_arch_disable(struct vpci_arch_msi *arch, struct pci_dev > *pdev, > + unsigned int vectors) > +{ > + unsigned int i; > + > + ASSERT(arch->pirq != -1); > + > + for ( i = 0; i < vectors; i++ ) > + { > + xen_domctl_bind_pt_irq_t bind = { > + .machine_irq = arch->pirq + i, > + .irq_type = PT_IRQ_TYPE_MSI, > + }; > + > + pcidevs_lock(); > + pt_irq_destroy_bind(pdev->domain, &bind); > + pcidevs_unlock(); > + } > + > + pcidevs_lock(); > + spin_lock(&pdev->domain->event_lock); > + unmap_domain_pirq(pdev->domain, arch->pirq); > + spin_unlock(&pdev->domain->event_lock); > + pcidevs_unlock(); > + > + arch->pirq = -1; > + > + return 0; > +} > + > +int vpci_msi_arch_init(struct vpci_arch_msi *arch) > +{ > + arch->pirq = -1; > + return 0; > +} > + > +void vpci_msi_arch_print(struct vpci_arch_msi *arch, uint16_t data, > + uint64_t addr) > +{ > + printk("vec=%#02x%7s%6s%3sassert%5s%7s dest_id=%lu pirq: %d\n", > + MASK_EXTR(data, MSI_DATA_VECTOR_MASK), > + data & MSI_DATA_DELIVERY_LOWPRI ? "lowest" : "fixed", > + data & MSI_DATA_TRIGGER_LEVEL ? "level" : "edge", > + data & MSI_DATA_LEVEL_ASSERT ? "" : "de", > + addr & MSI_ADDR_DESTMODE_LOGIC ? "log" : "phys", > + addr & MSI_ADDR_REDIRECTION_LOWPRI ? "lowest" : "cpu", > + MASK_EXTR(addr, MSI_ADDR_DEST_ID_MASK), > + arch->pirq); > +} > diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c > index d98f400699..573378d6c3 100644 > --- a/xen/arch/x86/msi.c > +++ b/xen/arch/x86/msi.c > @@ -30,6 +30,7 @@ > #include <public/physdev.h> > #include <xen/iommu.h> > #include <xsm/xsm.h> > +#include <xen/vpci.h> > > static s8 __read_mostly use_msi = -1; > boolean_param("msi", use_msi); > @@ -1536,6 +1537,8 @@ static void dump_msi(unsigned char key) > attr.guest_masked ? 'G' : ' ', > mask); > } > + > + vpci_dump_msi(); > } > > static int __init msi_setup_keyhandler(void) > diff --git a/xen/drivers/vpci/Makefile b/xen/drivers/vpci/Makefile > index 241467212f..62cec9e82b 100644 > --- a/xen/drivers/vpci/Makefile > +++ b/xen/drivers/vpci/Makefile > @@ -1 +1 @@ > -obj-y += vpci.o header.o > +obj-y += vpci.o header.o msi.o > diff --git a/xen/drivers/vpci/msi.c b/xen/drivers/vpci/msi.c > new file mode 100644 > index 0000000000..d8f3418616 > --- /dev/null > +++ b/xen/drivers/vpci/msi.c > @@ -0,0 +1,348 @@ > +/* > + * Handlers for accesses to the MSI capability structure. > + * > + * Copyright (C) 2017 Citrix Systems R&D > + * > + * 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 that 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, see > <http://www.gnu.org/licenses/>. > + */ > + > +#include <xen/sched.h> > +#include <xen/vpci.h> > +#include <asm/msi.h> > +#include <xen/keyhandler.h> > + > +/* Handlers for the MSI control field (PCI_MSI_FLAGS). */ > +static void vpci_msi_control_read(struct pci_dev *pdev, unsigned int reg, > + union vpci_val *val, void *data) > +{ > + const struct vpci_msi *msi = data; > + > + /* Set multiple message capable. */ > + val->u16 = MASK_INSR(fls(msi->max_vectors) - 1, > PCI_MSI_FLAGS_QMASK); > + > + if ( msi->enabled ) { > + val->u16 |= PCI_MSI_FLAGS_ENABLE; > + val->u16 |= MASK_INSR(fls(msi->vectors) - 1, PCI_MSI_FLAGS_QSIZE); > + } > + val->u16 |= msi->masking ? PCI_MSI_FLAGS_MASKBIT : 0; > + val->u16 |= msi->address64 ? PCI_MSI_FLAGS_64BIT : 0; > +} > + > +static void vpci_msi_enable(struct pci_dev *pdev, struct vpci_msi *msi, > + unsigned int vectors) > +{ > + int ret; > + > + ASSERT(!msi->vectors); > + > + ret = vpci_msi_arch_enable(&msi->arch, pdev, msi->address, msi->data, > + vectors); > + if ( ret ) > + return; > + > + /* Apply the mask bits. */ > + if ( msi->masking ) > + { > + unsigned int i; > + uint32_t mask = msi->mask; > + > + for ( i = ffs(mask) - 1; mask && i < vectors; i = ffs(mask) - 1 ) > + { > + vpci_msi_arch_mask(&msi->arch, pdev, i, true); > + __clear_bit(i, &mask); > + } > + } > + > + __msi_set_enable(pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn), > + PCI_FUNC(pdev->devfn), msi->pos, 1); > + > + msi->vectors = vectors; > + msi->enabled = true; > +} > + > +static int vpci_msi_disable(struct pci_dev *pdev, struct vpci_msi *msi) > +{ > + int ret; > + > + ASSERT(msi->vectors); > + > + __msi_set_enable(pdev->seg, pdev->bus, PCI_SLOT(pdev->devfn), > + PCI_FUNC(pdev->devfn), msi->pos, 0); > + > + ret = vpci_msi_arch_disable(&msi->arch, pdev, msi->vectors); > + if ( ret ) > + return ret; > + > + msi->vectors = 0; > + msi->enabled = false; > + > + return 0; > +} > + > +static void vpci_msi_control_write(struct pci_dev *pdev, unsigned int reg, > + union vpci_val val, void *data) > +{ > + struct vpci_msi *msi = data; > + unsigned int vectors = 1 << MASK_EXTR(val.u16, PCI_MSI_FLAGS_QSIZE); > + int ret; > + > + if ( vectors > msi->max_vectors ) > + vectors = msi->max_vectors; > + > + if ( !!(val.u16 & PCI_MSI_FLAGS_ENABLE) == msi->enabled && > + (vectors == msi->vectors || !msi->enabled) ) > + return; Personally I find the above logic a little tricky to follow. Would it be clearer to fold it into the logic below? (I only understood the reason for the logic above after reading the logic below). > + > + if ( val.u16 & PCI_MSI_FLAGS_ENABLE ) > + { > + if ( msi->enabled ) > + { > + /* > + * Change to the number of enabled vectors, disable and > + * enable MSI in order to apply it. > + */ > + ret = vpci_msi_disable(pdev, msi); > + if ( ret ) > + return; > + } > + vpci_msi_enable(pdev, msi, vectors); > + } > + else > + vpci_msi_disable(pdev, msi); > +} > + > +/* Handlers for the address field (32bit or low part of a 64bit address). */ > +static void vpci_msi_address_read(struct pci_dev *pdev, unsigned int reg, > + union vpci_val *val, void *data) > +{ > + const struct vpci_msi *msi = data; > + > + val->u32 = msi->address; > +} > + > +static void vpci_msi_address_write(struct pci_dev *pdev, unsigned int reg, > + union vpci_val val, void *data) > +{ > + struct vpci_msi *msi = data; > + > + /* Clear low part. */ > + msi->address &= ~(uint64_t)0xffffffff; > + msi->address |= val.u32; > +} > + > +/* Handlers for the high part of a 64bit address field. */ > +static void vpci_msi_address_upper_read(struct pci_dev *pdev, unsigned > int reg, > + union vpci_val *val, void *data) > +{ > + const struct vpci_msi *msi = data; > + > + val->u32 = msi->address >> 32; > +} > + > +static void vpci_msi_address_upper_write(struct pci_dev *pdev, unsigned > int reg, > + union vpci_val val, void *data) > +{ > + struct vpci_msi *msi = data; > + > + /* Clear high part. */ > + msi->address &= ~((uint64_t)0xffffffff << 32); > + msi->address |= (uint64_t)val.u32 << 32; > +} > + > +/* Handlers for the data field. */ > +static void vpci_msi_data_read(struct pci_dev *pdev, unsigned int reg, > + union vpci_val *val, void *data) > +{ > + const struct vpci_msi *msi = data; > + > + val->u16 = msi->data; > +} > + > +static void vpci_msi_data_write(struct pci_dev *pdev, unsigned int reg, > + union vpci_val val, void *data) > +{ > + struct vpci_msi *msi = data; > + > + msi->data = val.u16; > +} > + > +static void vpci_msi_mask_read(struct pci_dev *pdev, unsigned int reg, > + union vpci_val *val, void *data) > +{ > + const struct vpci_msi *msi = data; > + > + val->u32 = msi->mask; > +} > + > +static void vpci_msi_mask_write(struct pci_dev *pdev, unsigned int reg, > + union vpci_val val, void *data) > +{ > + struct vpci_msi *msi = data; > + uint32_t dmask; > + > + dmask = msi->mask ^ val.u32; > + > + if ( !dmask ) > + return; > + > + if ( msi->enabled ) > + { > + unsigned int i; > + > + for ( i = ffs(dmask) - 1; dmask && i < msi->vectors; > + i = ffs(dmask) - 1 ) > + { > + vpci_msi_arch_mask(&msi->arch, pdev, i, MASK_EXTR(val.u32, 1 << > i)); > + __clear_bit(i, &dmask); > + } > + } > + > + msi->mask = val.u32; > +} > + > +static int vpci_init_msi(struct pci_dev *pdev) > +{ > + uint8_t seg = pdev->seg, bus = pdev->bus; > + uint8_t slot = PCI_SLOT(pdev->devfn), func = PCI_FUNC(pdev->devfn); > + struct vpci_msi *msi; > + unsigned int msi_offset; > + uint16_t control; > + int ret; > + > + msi_offset = pci_find_cap_offset(seg, bus, slot, func, PCI_CAP_ID_MSI); > + if ( !msi_offset ) > + return 0; > + > + msi = xzalloc(struct vpci_msi); > + if ( !msi ) > + return -ENOMEM; > + > + msi->pos = msi_offset; > + > + control = pci_conf_read16(seg, bus, slot, func, > + msi_control_reg(msi_offset)); > + > + ret = vpci_add_register(pdev, vpci_msi_control_read, > + vpci_msi_control_write, > + msi_control_reg(msi_offset), 2, msi); > + if ( ret ) > + goto error; > + > + /* Get the maximum number of vectors the device supports. */ > + msi->max_vectors = multi_msi_capable(control); > + ASSERT(msi->max_vectors <= 32); > + > + /* No PIRQ bind yet. */ > + vpci_msi_arch_init(&msi->arch); > + > + if ( is_64bit_address(control) ) > + msi->address64 = true; > + if ( is_mask_bit_support(control) ) > + msi->masking = true; > + > + ret = vpci_add_register(pdev, vpci_msi_address_read, > + vpci_msi_address_write, > + msi_lower_address_reg(msi_offset), 4, msi); > + if ( ret ) > + goto error; > + > + ret = vpci_add_register(pdev, vpci_msi_data_read, vpci_msi_data_write, > + msi_data_reg(msi_offset, msi->address64), 2, > + msi); > + if ( ret ) > + goto error; > + > + if ( msi->address64 ) > + { > + ret = vpci_add_register(pdev, vpci_msi_address_upper_read, > + vpci_msi_address_upper_write, > + msi_upper_address_reg(msi_offset), 4, msi); > + if ( ret ) > + goto error; > + } > + > + if ( msi->masking ) > + { > + ret = vpci_add_register(pdev, vpci_msi_mask_read, > vpci_msi_mask_write, > + msi_mask_bits_reg(msi_offset, > + msi->address64), 4, msi); > + if ( ret ) > + goto error; > + } > + > + pdev->vpci->msi = msi; > + > + return 0; > + > + error: Do you not need to clean up any added register handlers here? They have been given a context value which you're about to xfree(). Paul > + ASSERT(ret); > + xfree(msi); > + return ret; > +} > + > +REGISTER_VPCI_INIT(vpci_init_msi); > + > +void vpci_dump_msi(void) > +{ > + struct domain *d; > + > + for_each_domain ( d ) > + { > + const struct pci_dev *pdev; > + > + if ( !has_vpci(d) ) > + continue; > + > + printk("vPCI MSI information for guest %u\n", d->domain_id); > + > + if ( !vpci_trylock(d) ) > + { > + printk("Unable to get vPCI lock, skipping\n"); > + continue; > + } > + > + list_for_each_entry ( pdev, &d->arch.pdev_list, domain_list ) > + { > + uint8_t seg = pdev->seg, bus = pdev->bus; > + uint8_t slot = PCI_SLOT(pdev->devfn), func = PCI_FUNC(pdev- > >devfn); > + struct vpci_msi *msi = pdev->vpci->msi; > + > + if ( !msi ) > + continue; > + > + printk("Device %04x:%02x:%02x.%u\n", seg, bus, slot, func); > + > + printk("Enabled: %u Supports masking: %u 64-bit addresses: %u\n", > + msi->enabled, msi->masking, msi->address64); > + printk("Max vectors: %u enabled vectors: %u\n", > + msi->max_vectors, msi->vectors); > + > + vpci_msi_arch_print(&msi->arch, msi->data, msi->address); > + > + if ( msi->masking ) > + printk("mask=%#032x\n", msi->mask); > + } > + vpci_unlock(d); > + } > +} > + > +/* > + * Local variables: > + * mode: C > + * c-file-style: "BSD" > + * c-basic-offset: 4 > + * tab-width: 4 > + * indent-tabs-mode: nil > + * End: > + */ > + > diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h > index 4fe996fe49..55ed094734 100644 > --- a/xen/include/asm-x86/hvm/io.h > +++ b/xen/include/asm-x86/hvm/io.h > @@ -20,6 +20,7 @@ > #define __ASM_X86_HVM_IO_H__ > > #include <xen/mm.h> > +#include <xen/pci.h> > #include <asm/hvm/vpic.h> > #include <asm/hvm/vioapic.h> > #include <public/hvm/ioreq.h> > @@ -126,6 +127,23 @@ void hvm_dpci_eoi(struct domain *d, unsigned int > guest_irq, > void msix_write_completion(struct vcpu *); > void msixtbl_init(struct domain *d); > > +/* Arch-specific MSI data for vPCI. */ > +struct vpci_arch_msi { > + int pirq; > +}; > + > +/* Arch-specific vPCI MSI helpers. */ > +void vpci_msi_arch_mask(struct vpci_arch_msi *arch, struct pci_dev *pdev, > + unsigned int entry, bool mask); > +int vpci_msi_arch_enable(struct vpci_arch_msi *arch, struct pci_dev *pdev, > + uint64_t address, uint32_t data, > + unsigned int vectors); > +int vpci_msi_arch_disable(struct vpci_arch_msi *arch, struct pci_dev > *pdev, > + unsigned int vectors); > +int vpci_msi_arch_init(struct vpci_arch_msi *arch); > +void vpci_msi_arch_print(struct vpci_arch_msi *arch, uint16_t data, > + uint64_t addr); > + > enum stdvga_cache_state { > STDVGA_CACHE_UNINITIALIZED, > STDVGA_CACHE_ENABLED, > diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h > index 213ee53f72..9c36c34372 100644 > --- a/xen/include/asm-x86/msi.h > +++ b/xen/include/asm-x86/msi.h > @@ -48,6 +48,7 @@ > #define MSI_ADDR_REDIRECTION_SHIFT 3 > #define MSI_ADDR_REDIRECTION_CPU (0 << > MSI_ADDR_REDIRECTION_SHIFT) > #define MSI_ADDR_REDIRECTION_LOWPRI (1 << > MSI_ADDR_REDIRECTION_SHIFT) > +#define MSI_ADDR_REDIRECTION_MASK 0x8 > > #define MSI_ADDR_DEST_ID_SHIFT 12 > #define MSI_ADDR_DEST_ID_MASK 0x00ff000 > diff --git a/xen/include/xen/hvm/irq.h b/xen/include/xen/hvm/irq.h > index 0d2c72c109..d07185a479 100644 > --- a/xen/include/xen/hvm/irq.h > +++ b/xen/include/xen/hvm/irq.h > @@ -57,7 +57,9 @@ struct dev_intx_gsi_link { > #define VMSI_DELIV_MASK 0x7000 > #define VMSI_TRIG_MODE 0x8000 > > +#define GFLAGS_SHIFT_DEST_ID 0 > #define GFLAGS_SHIFT_RH 8 > +#define GFLAGS_SHIFT_DM 9 > #define GFLAGS_SHIFT_DELIV_MODE 12 > #define GFLAGS_SHIFT_TRG_MODE 15 > > diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h > index 452ee482e8..2a7d7557b3 100644 > --- a/xen/include/xen/vpci.h > +++ b/xen/include/xen/vpci.h > @@ -13,6 +13,7 @@ > * of just returning whether the lock is hold by any CPU). > */ > #define vpci_lock(d) spin_lock_recursive(&(d)- > >arch.hvm_domain.vpci_lock) > +#define vpci_trylock(d) spin_trylock_recursive(&(d)- > >arch.hvm_domain.vpci_lock) > #define vpci_unlock(d) spin_unlock_recursive(&(d)- > >arch.hvm_domain.vpci_lock) > #define vpci_locked(d) spin_is_locked(&(d)->arch.hvm_domain.vpci_lock) > > @@ -85,9 +86,34 @@ struct vpci { > } bars[7]; /* At most 6 BARS + 1 expansion ROM BAR. */ > /* FIXME: currently there's no support for SR-IOV. */ > } header; > + > + /* MSI data. */ > + struct vpci_msi { > + /* Offset of the capability in the config space. */ > + unsigned int pos; > + /* Maximum number of vectors supported by the device. */ > + unsigned int max_vectors; > + /* Number of vectors configured. */ > + unsigned int vectors; > + /* Address and data fields. */ > + uint64_t address; > + uint16_t data; > + /* Mask bitfield. */ > + uint32_t mask; > + /* Enabled? */ > + bool enabled; > + /* Supports per-vector masking? */ > + bool masking; > + /* 64-bit address capable? */ > + bool address64; > + /* Arch-specific data. */ > + struct vpci_arch_msi arch; > + } *msi; > #endif > }; > > +void vpci_dump_msi(void); > + > #endif > > /* > -- > 2.11.0 (Apple Git-81) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |