debuggers.hg

changeset 20884:ba6a71530fc6

x86: add keyhandler to dump MSI state

Equivalent to dumping IO-APIC state; the question is whether this
ought to live on its own key (as done here), or whether it should be
chanined to from the 'i' handler.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu Jan 21 15:12:17 2010 +0000 (2010-01-21)
parents d1efaaee441b
children 57893d13574c
files xen/arch/x86/msi.c
line diff
     1.1 --- a/xen/arch/x86/msi.c	Thu Jan 21 14:40:05 2010 +0000
     1.2 +++ b/xen/arch/x86/msi.c	Thu Jan 21 15:12:17 2010 +0000
     1.3 @@ -391,6 +391,21 @@ static void msi_set_mask_bit(unsigned in
     1.4      entry->msi_attrib.masked = !!flag;
     1.5  }
     1.6  
     1.7 +static int msi_get_mask_bit(const struct msi_desc *entry)
     1.8 +{
     1.9 +    switch (entry->msi_attrib.type) {
    1.10 +    case PCI_CAP_ID_MSI:
    1.11 +        if (!entry->dev || !entry->msi_attrib.maskbit)
    1.12 +            break;
    1.13 +        return pci_conf_read32(entry->dev->bus, PCI_SLOT(entry->dev->devfn),
    1.14 +                               PCI_FUNC(entry->dev->devfn),
    1.15 +                               (unsigned long)entry->mask_base) & 1;
    1.16 +    case PCI_CAP_ID_MSIX:
    1.17 +        return readl(entry->mask_base + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET) & 1;
    1.18 +    }
    1.19 +    return -1;
    1.20 +}
    1.21 +
    1.22  void mask_msi_irq(unsigned int irq)
    1.23  {
    1.24      msi_set_mask_bit(irq, 1);
    1.25 @@ -834,3 +849,65 @@ unsigned int pci_msix_get_table_len(stru
    1.26  
    1.27      return len;
    1.28  }
    1.29 +
    1.30 +static void dump_msi(unsigned char key)
    1.31 +{
    1.32 +    unsigned int irq;
    1.33 +
    1.34 +    printk("PCI-MSI interrupt information:\n");
    1.35 +
    1.36 +    for ( irq = 0; irq < nr_irqs; irq++ )
    1.37 +    {
    1.38 +        struct irq_desc *desc = irq_to_desc(irq);
    1.39 +        const struct msi_desc *entry;
    1.40 +        u32 addr, data;
    1.41 +        unsigned long flags;
    1.42 +        char type;
    1.43 +
    1.44 +        spin_lock_irqsave(&desc->lock, flags);
    1.45 +
    1.46 +        entry = desc->msi_desc;
    1.47 +        type = desc->handler == &pci_msi_type && entry;
    1.48 +
    1.49 +        spin_unlock_irqrestore(&desc->lock, flags);
    1.50 +
    1.51 +        if ( !type )
    1.52 +            continue;
    1.53 +
    1.54 +        switch ( entry->msi_attrib.type )
    1.55 +        {
    1.56 +        case PCI_CAP_ID_MSI: type = ' '; break;
    1.57 +        case PCI_CAP_ID_MSIX: type = 'X'; break;
    1.58 +        default: type = '?'; break;
    1.59 +        }
    1.60 +
    1.61 +        data = entry->msg.data;
    1.62 +        addr = entry->msg.address_lo;
    1.63 +
    1.64 +        printk(" MSI%c %4u vec=%02x%7s%6s%3sassert%5s%7s"
    1.65 +               " dest=%08x mask=%d/%d/%d\n",
    1.66 +               type, irq,
    1.67 +               (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT,
    1.68 +               data & MSI_DATA_DELIVERY_LOWPRI ? "lowest" : "fixed",
    1.69 +               data & MSI_DATA_TRIGGER_LEVEL ? "level" : "edge",
    1.70 +               data & MSI_DATA_LEVEL_ASSERT ? "" : "de",
    1.71 +               addr & MSI_ADDR_DESTMODE_LOGIC ? "log" : "phys",
    1.72 +               addr & MSI_ADDR_REDIRECTION_LOWPRI ? "lowest" : "cpu",
    1.73 +               entry->msg.dest32,
    1.74 +               entry->msi_attrib.maskbit, entry->msi_attrib.masked,
    1.75 +               msi_get_mask_bit(entry));
    1.76 +    }
    1.77 +}
    1.78 +
    1.79 +static struct keyhandler dump_msi_keyhandler = {
    1.80 +    .diagnostic = 1,
    1.81 +    .u.fn = dump_msi,
    1.82 +    .desc = "dump MSI state"
    1.83 +};
    1.84 +
    1.85 +static int __init msi_setup_keyhandler(void)
    1.86 +{
    1.87 +    register_keyhandler('M', &dump_msi_keyhandler);
    1.88 +    return 0;
    1.89 +}
    1.90 +__initcall(msi_setup_keyhandler);