xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Wei Wang <wei.wang2@amd.com>
To: Jan Beulich <JBeulich@suse.com>
Cc: xen-devel <xen-devel@lists.xen.org>
Subject: Re: [PATCH 2/3] amd iommu: use base platform MSI implementation
Date: Thu, 13 Sep 2012 15:51:13 +0200	[thread overview]
Message-ID: <5051E4D1.1060207@amd.com> (raw)
In-Reply-To: <5051A24A020000780009AF77@nat28.tlf.novell.com>

This version works well. Acked.
Thanks,
Wei

On 09/13/2012 09:07 AM, Jan Beulich wrote:
>>>> On 12.09.12 at 14:47, Wei Wang<wei.wang2@amd.com>  wrote:
>> I found this patch triggered a xen BUG
>
> Indeed - my default builds don't use high enough a CPU count to
> see this. I'm sorry for that. Below a drop-in replacement for the
> patch (it would unlikely apply cleanly to the tip of staging unstable
> due to Keir's cleanup after the removal of x86-32 support.
>
> Jan
>
> --- 2012-09-11.orig/xen/arch/x86/msi.c	2012-09-13 08:40:47.000000000 +0200
> +++ 2012-09-11/xen/arch/x86/msi.c	2012-09-13 08:43:21.000000000 +0200
> @@ -13,6 +13,7 @@
>   #include<xen/delay.h>
>   #include<xen/sched.h>
>   #include<xen/acpi.h>
> +#include<xen/cpu.h>
>   #include<xen/errno.h>
>   #include<xen/pci.h>
>   #include<xen/pci_regs.h>
> @@ -32,8 +33,9 @@
>   #include<xsm/xsm.h>
>
>   /* bitmap indicate which fixed map is free */
> -DEFINE_SPINLOCK(msix_fixmap_lock);
> -DECLARE_BITMAP(msix_fixmap_pages, FIX_MSIX_MAX_PAGES);
> +static DEFINE_SPINLOCK(msix_fixmap_lock);
> +static DECLARE_BITMAP(msix_fixmap_pages, FIX_MSIX_MAX_PAGES);
> +static DEFINE_PER_CPU(cpumask_var_t, scratch_mask);
>
>   static int msix_fixmap_alloc(void)
>   {
> @@ -126,13 +128,17 @@ void msi_compose_msg(struct irq_desc *de
>       unsigned dest;
>       int vector = desc->arch.vector;
>
> -    if ( cpumask_empty(desc->arch.cpu_mask) ) {
> +    memset(msg, 0, sizeof(*msg));
> +    if ( !cpumask_intersects(desc->arch.cpu_mask,&cpu_online_map) ) {
>           dprintk(XENLOG_ERR,"%s, compose msi message error!!\n", __func__);
>           return;
>       }
>
>       if ( vector ) {
> -        dest = cpu_mask_to_apicid(desc->arch.cpu_mask);
> +        cpumask_t *mask = this_cpu(scratch_mask);
> +
> +        cpumask_and(mask, desc->arch.cpu_mask,&cpu_online_map);
> +        dest = cpu_mask_to_apicid(mask);
>
>           msg->address_hi = MSI_ADDR_BASE_HI;
>           msg->address_lo =
> @@ -281,23 +287,27 @@ static void set_msi_affinity(struct irq_
>       write_msi_msg(msi_desc,&msg);
>   }
>
> +void __msi_set_enable(u16 seg, u8 bus, u8 slot, u8 func, int pos, int enable)
> +{
> +    u16 control = pci_conf_read16(seg, bus, slot, func, pos + PCI_MSI_FLAGS);
> +
> +    control&= ~PCI_MSI_FLAGS_ENABLE;
> +    if ( enable )
> +        control |= PCI_MSI_FLAGS_ENABLE;
> +    pci_conf_write16(seg, bus, slot, func, pos + PCI_MSI_FLAGS, control);
> +}
> +
>   static void msi_set_enable(struct pci_dev *dev, int enable)
>   {
>       int pos;
> -    u16 control, seg = dev->seg;
> +    u16 seg = dev->seg;
>       u8 bus = dev->bus;
>       u8 slot = PCI_SLOT(dev->devfn);
>       u8 func = PCI_FUNC(dev->devfn);
>
>       pos = pci_find_cap_offset(seg, bus, slot, func, PCI_CAP_ID_MSI);
>       if ( pos )
> -    {
> -        control = pci_conf_read16(seg, bus, slot, func, pos + PCI_MSI_FLAGS);
> -        control&= ~PCI_MSI_FLAGS_ENABLE;
> -        if ( enable )
> -            control |= PCI_MSI_FLAGS_ENABLE;
> -        pci_conf_write16(seg, bus, slot, func, pos + PCI_MSI_FLAGS, control);
> -    }
> +        __msi_set_enable(seg, bus, slot, func, pos, enable);
>   }
>
>   static void msix_set_enable(struct pci_dev *dev, int enable)
> @@ -379,12 +389,12 @@ static int msi_get_mask_bit(const struct
>       return -1;
>   }
>
> -static void mask_msi_irq(struct irq_desc *desc)
> +void mask_msi_irq(struct irq_desc *desc)
>   {
>       msi_set_mask_bit(desc, 1);
>   }
>
> -static void unmask_msi_irq(struct irq_desc *desc)
> +void unmask_msi_irq(struct irq_desc *desc)
>   {
>       msi_set_mask_bit(desc, 0);
>   }
> @@ -395,7 +405,7 @@ static unsigned int startup_msi_irq(stru
>       return 0;
>   }
>
> -static void ack_nonmaskable_msi_irq(struct irq_desc *desc)
> +void ack_nonmaskable_msi_irq(struct irq_desc *desc)
>   {
>       irq_complete_move(desc);
>       move_native_irq(desc);
> @@ -407,7 +417,7 @@ static void ack_maskable_msi_irq(struct
>       ack_APIC_irq(); /* ACKTYPE_NONE */
>   }
>
> -static void end_nonmaskable_msi_irq(struct irq_desc *desc, u8 vector)
> +void end_nonmaskable_msi_irq(struct irq_desc *desc, u8 vector)
>   {
>       ack_APIC_irq(); /* ACKTYPE_EOI */
>   }
> @@ -1071,6 +1081,39 @@ unsigned int pci_msix_get_table_len(stru
>       return len;
>   }
>
> +static int msi_cpu_callback(
> +    struct notifier_block *nfb, unsigned long action, void *hcpu)
> +{
> +    unsigned int cpu = (unsigned long)hcpu;
> +    int rc = 0;
> +
> +    switch ( action )
> +    {
> +    case CPU_UP_PREPARE:
> +        if ( !alloc_cpumask_var(&per_cpu(scratch_mask, cpu)) )
> +            rc = -ENOMEM;
> +        break;
> +    case CPU_UP_CANCELED:
> +    case CPU_DEAD:
> +        free_cpumask_var(per_cpu(scratch_mask, cpu));
> +        break;
> +    default:
> +        break;
> +    }
> +
> +    return notifier_from_errno(rc);
> +}
> +
> +static struct notifier_block msi_cpu_nfb = {
> +    .notifier_call = msi_cpu_callback
> +};
> +
> +void __init early_msi_init(void)
> +{
> +    register_cpu_notifier(&msi_cpu_nfb);
> +    msi_cpu_callback(&msi_cpu_nfb, CPU_UP_PREPARE, NULL);
> +}
> +
>   static void dump_msi(unsigned char key)
>   {
>       unsigned int irq;
> --- 2012-09-11.orig/xen/arch/x86/setup.c	2012-09-03 08:25:31.000000000 +0200
> +++ 2012-09-11/xen/arch/x86/setup.c	2012-09-13 08:44:49.000000000 +0200
> @@ -35,6 +35,7 @@
>   #include<asm/processor.h>
>   #include<asm/mpspec.h>
>   #include<asm/apic.h>
> +#include<asm/msi.h>
>   #include<asm/desc.h>
>   #include<asm/paging.h>
>   #include<asm/e820.h>
> @@ -1274,6 +1275,8 @@ void __init __start_xen(unsigned long mb
>       acpi_mmcfg_init();
>   #endif
>
> +    early_msi_init();
> +
>       iommu_setup();    /* setup iommu if available */
>
>       smp_prepare_cpus(max_cpus);
> --- 2012-09-11.orig/xen/drivers/passthrough/amd/iommu_detect.c	2012-09-13 08:40:47.000000000 +0200
> +++ 2012-09-11/xen/drivers/passthrough/amd/iommu_detect.c	2012-06-20 17:33:15.000000000 +0200
> @@ -31,7 +31,6 @@ static int __init get_iommu_msi_capabili
>       u16 seg, u8 bus, u8 dev, u8 func, struct amd_iommu *iommu)
>   {
>       int pos;
> -    u16 control;
>
>       pos = pci_find_cap_offset(seg, bus, dev, func, PCI_CAP_ID_MSI);
>
> @@ -41,9 +40,6 @@ static int __init get_iommu_msi_capabili
>       AMD_IOMMU_DEBUG("Found MSI capability block at %#x\n", pos);
>
>       iommu->msi_cap = pos;
> -    control = pci_conf_read16(seg, bus, dev, func,
> -                              iommu->msi_cap + PCI_MSI_FLAGS);
> -    iommu->maskbit = control&  PCI_MSI_FLAGS_MASKBIT;
>       return 0;
>   }
>
> --- 2012-09-11.orig/xen/drivers/passthrough/amd/iommu_init.c	2012-06-13 08:39:38.000000000 +0200
> +++ 2012-09-11/xen/drivers/passthrough/amd/iommu_init.c	2012-09-11 11:26:28.000000000 +0200
> @@ -467,20 +467,9 @@ static void iommu_msi_set_affinity(struc
>           return;
>       }
>
> -    memset(&msg, 0, sizeof(msg));
> -    msg.data = MSI_DATA_VECTOR(desc->arch.vector)&  0xff;
> -    msg.data |= 1<<  14;
> -    msg.data |= (INT_DELIVERY_MODE != dest_LowestPrio) ?
> -        MSI_DATA_DELIVERY_FIXED:
> -        MSI_DATA_DELIVERY_LOWPRI;
> -
> -    msg.address_hi =0;
> -    msg.address_lo = (MSI_ADDRESS_HEADER<<  (MSI_ADDRESS_HEADER_SHIFT + 8));
> -    msg.address_lo |= INT_DEST_MODE ? MSI_ADDR_DESTMODE_LOGIC:
> -                    MSI_ADDR_DESTMODE_PHYS;
> -    msg.address_lo |= (INT_DELIVERY_MODE != dest_LowestPrio) ?
> -                    MSI_ADDR_REDIRECTION_CPU:
> -                    MSI_ADDR_REDIRECTION_LOWPRI;
> +    msi_compose_msg(desc,&msg);
> +    /* Is this override really needed? */
> +    msg.address_lo&= ~MSI_ADDR_DEST_ID_MASK;
>       msg.address_lo |= MSI_ADDR_DEST_ID(dest&  0xff);
>
>       pci_conf_write32(seg, bus, dev, func,
> @@ -494,18 +483,8 @@ static void iommu_msi_set_affinity(struc
>
>   static void amd_iommu_msi_enable(struct amd_iommu *iommu, int flag)
>   {
> -    u16 control;
> -    int bus = PCI_BUS(iommu->bdf);
> -    int dev = PCI_SLOT(iommu->bdf);
> -    int func = PCI_FUNC(iommu->bdf);
> -
> -    control = pci_conf_read16(iommu->seg, bus, dev, func,
> -        iommu->msi_cap + PCI_MSI_FLAGS);
> -    control&= ~PCI_MSI_FLAGS_ENABLE;
> -    if ( flag )
> -        control |= flag;
> -    pci_conf_write16(iommu->seg, bus, dev, func,
> -        iommu->msi_cap + PCI_MSI_FLAGS, control);
> +    __msi_set_enable(iommu->seg, PCI_BUS(iommu->bdf), PCI_SLOT(iommu->bdf),
> +                     PCI_FUNC(iommu->bdf), iommu->msi_cap, flag);
>   }
>
>   static void iommu_msi_unmask(struct irq_desc *desc)
> @@ -513,10 +492,6 @@ static void iommu_msi_unmask(struct irq_
>       unsigned long flags;
>       struct amd_iommu *iommu = desc->action->dev_id;
>
> -    /* FIXME: do not support mask bits at the moment */
> -    if ( iommu->maskbit )
> -        return;
> -
>       spin_lock_irqsave(&iommu->lock, flags);
>       amd_iommu_msi_enable(iommu, IOMMU_CONTROL_ENABLED);
>       spin_unlock_irqrestore(&iommu->lock, flags);
> @@ -529,10 +504,6 @@ static void iommu_msi_mask(struct irq_de
>
>       irq_complete_move(desc);
>
> -    /* FIXME: do not support mask bits at the moment */
> -    if ( iommu->maskbit )
> -        return;
> -
>       spin_lock_irqsave(&iommu->lock, flags);
>       amd_iommu_msi_enable(iommu, IOMMU_CONTROL_DISABLED);
>       spin_unlock_irqrestore(&iommu->lock, flags);
> @@ -562,6 +533,37 @@ static hw_irq_controller iommu_msi_type
>       .set_affinity = iommu_msi_set_affinity,
>   };
>
> +static unsigned int iommu_maskable_msi_startup(struct irq_desc *desc)
> +{
> +    iommu_msi_unmask(desc);
> +    unmask_msi_irq(desc);
> +    return 0;
> +}
> +
> +static void iommu_maskable_msi_shutdown(struct irq_desc *desc)
> +{
> +    mask_msi_irq(desc);
> +    iommu_msi_mask(desc);
> +}
> +
> +/*
> + * While the names may appear mismatched, we indeed want to use the non-
> + * maskable flavors here, as we want the ACK to be issued in ->end().
> + */
> +#define iommu_maskable_msi_ack ack_nonmaskable_msi_irq
> +#define iommu_maskable_msi_end end_nonmaskable_msi_irq
> +
> +static hw_irq_controller iommu_maskable_msi_type = {
> +    .typename = "IOMMU-M-MSI",
> +    .startup = iommu_maskable_msi_startup,
> +    .shutdown = iommu_maskable_msi_shutdown,
> +    .enable = unmask_msi_irq,
> +    .disable = mask_msi_irq,
> +    .ack = iommu_maskable_msi_ack,
> +    .end = iommu_maskable_msi_end,
> +    .set_affinity = iommu_msi_set_affinity,
> +};
> +
>   static void parse_event_log_entry(struct amd_iommu *iommu, u32 entry[])
>   {
>       u16 domain_id, device_id, bdf, cword, flags;
> @@ -784,6 +786,7 @@ static void iommu_interrupt_handler(int
>   static int __init set_iommu_interrupt_handler(struct amd_iommu *iommu)
>   {
>       int irq, ret;
> +    u16 control;
>
>       irq = create_irq(NUMA_NO_NODE);
>       if ( irq<= 0 )
> @@ -792,7 +795,11 @@ static int __init set_iommu_interrupt_ha
>           return 0;
>       }
>
> -    irq_desc[irq].handler =&iommu_msi_type;
> +    control = pci_conf_read16(iommu->seg, PCI_BUS(iommu->bdf),
> +                              PCI_SLOT(iommu->bdf), PCI_FUNC(iommu->bdf),
> +                              iommu->msi_cap + PCI_MSI_FLAGS);
> +    irq_desc[irq].handler = control&  PCI_MSI_FLAGS_MASKBIT ?
> +&iommu_maskable_msi_type :&iommu_msi_type;
>       ret = request_irq(irq, iommu_interrupt_handler, 0, "amd_iommu", iommu);
>       if ( ret )
>       {
> --- 2012-09-11.orig/xen/include/asm-x86/amd-iommu.h	2012-09-13 08:40:47.000000000 +0200
> +++ 2012-09-11/xen/include/asm-x86/amd-iommu.h	2012-06-13 10:23:45.000000000 +0200
> @@ -83,6 +83,7 @@ struct amd_iommu {
>       u16 seg;
>       u16 bdf;
>       u16 cap_offset;
> +    u8 msi_cap;
>       iommu_cap_t cap;
>
>       u8 ht_flags;
> @@ -101,9 +102,6 @@ struct amd_iommu {
>       uint64_t exclusion_base;
>       uint64_t exclusion_limit;
>
> -    int msi_cap;
> -    int maskbit;
> -
>       int enabled;
>       int irq;
>   };
> --- 2012-09-11.orig/xen/include/asm-x86/msi.h	2012-09-13 08:40:47.000000000 +0200
> +++ 2012-09-11/xen/include/asm-x86/msi.h	2012-09-13 08:45:14.000000000 +0200
> @@ -153,18 +153,6 @@ int msi_free_irq(struct msi_desc *entry)
>   /*
>    * MSI Defined Data Structures
>    */
> -#define MSI_ADDRESS_HEADER		0xfee
> -#define MSI_ADDRESS_HEADER_SHIFT	12
> -#define MSI_ADDRESS_HEADER_MASK		0xfff000
> -#define MSI_ADDRESS_DEST_ID_MASK	0xfff0000f
> -#define MSI_TARGET_CPU_MASK		0xff
> -#define MSI_TARGET_CPU_SHIFT		12
> -#define MSI_DELIVERY_MODE		0
> -#define MSI_LEVEL_MODE			1	/* Edge always assert */
> -#define MSI_TRIGGER_MODE		0	/* MSI is edge sensitive */
> -#define MSI_PHYSICAL_MODE		0
> -#define MSI_LOGICAL_MODE		1
> -#define MSI_REDIRECTION_HINT_MODE	0
>
>   struct msg_data {
>   #if defined(__LITTLE_ENDIAN_BITFIELD)
> @@ -212,6 +200,12 @@ struct msg_address {
>   	__u32 	hi_address;
>   } __attribute__ ((packed));
>
> +void early_msi_init(void);
>   void msi_compose_msg(struct irq_desc *, struct msi_msg *);
> +void __msi_set_enable(u16 seg, u8 bus, u8 slot, u8 func, int pos, int enable);
> +void mask_msi_irq(struct irq_desc *);
> +void unmask_msi_irq(struct irq_desc *);
> +void ack_nonmaskable_msi_irq(struct irq_desc *);
> +void end_nonmaskable_msi_irq(struct irq_desc *, u8 vector);
>
>   #endif /* __ASM_MSI_H */
>
>

      reply	other threads:[~2012-09-13 13:51 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-11 12:35 [PATCH 2/3] amd iommu: use base platform MSI implementation Jan Beulich
2012-09-12 12:47 ` Wei Wang
2012-09-13  7:07   ` Jan Beulich
2012-09-13 13:51     ` Wei Wang [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5051E4D1.1060207@amd.com \
    --to=wei.wang2@amd.com \
    --cc=JBeulich@suse.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).