All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] x86/IO-APIC: fix guest RTE write corner cases
@ 2013-05-08 12:51 Jan Beulich
  2013-05-14 14:52 ` Ping: " Jan Beulich
  0 siblings, 1 reply; 5+ messages in thread
From: Jan Beulich @ 2013-05-08 12:51 UTC (permalink / raw)
  To: xen-devel; +Cc: Keir Fraser, xiantao.zhang

[-- Attachment #1: Type: text/plain, Size: 3420 bytes --]

This fixes two regressions from c/s 20143:a7de5bd776ca ("x86: Make the
hypercall PHYSDEVOP_alloc_irq_vector hypercall dummy"):

For one, IRQs that had their vector set up by Xen internally without a
handler ever having got set (e.g. via "com<n>=..." without a matching
consumer option like "console=com<n>") would wrongly call
add_pin_to_irq() here, triggering the BUG_ON() in that function.

Second, when assign_irq_vector() fails this addition to irq_2_pin[]
needs to be undone.

In the context of this I'm also surprised that the irq_2_pin[]
manipulations here occur without any lock, i.e. rely on Dom0 to do
some sort of serialization.

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -133,6 +133,37 @@ static void add_pin_to_irq(unsigned int 
     share_vector_maps(irq_2_pin[irq].apic, apic);
 }
 
+static void remove_pin_from_irq(unsigned int irq, int apic, int pin)
+{
+    struct irq_pin_list *entry, *prev;
+
+    for (entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next]) {
+        if ((entry->apic == apic) && (entry->pin == pin))
+            break;
+        BUG_ON(!entry->next);
+    }
+
+    entry->pin = entry->apic = -1;
+
+    if (entry != &irq_2_pin[irq]) {
+        /* Removed entry is not at head of list. */
+        prev = &irq_2_pin[irq];
+        while (&irq_2_pin[prev->next] != entry)
+            prev = &irq_2_pin[prev->next];
+        prev->next = entry->next;
+    } else if (entry->next) {
+        /* Removed entry is at head of multi-item list. */
+        prev  = entry;
+        entry = &irq_2_pin[entry->next];
+        *prev = *entry;
+        entry->pin = entry->apic = -1;
+    } else
+        return;
+
+    entry->next = irq_2_pin_free_entry;
+    irq_2_pin_free_entry = entry - irq_2_pin;
+}
+
 /*
  * Reroute an IRQ to a different pin.
  */
@@ -2280,7 +2311,7 @@ int ioapic_guest_read(unsigned long phys
 
 int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
 {
-    int apic, pin, irq, ret, vector, pirq;
+    int apic, pin, irq, ret, pirq;
     struct IO_APIC_route_entry rte = { 0 };
     unsigned long flags;
     struct irq_desc *desc;
@@ -2348,13 +2379,25 @@ int ioapic_guest_write(unsigned long phy
         return 0;
     }
 
-    if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR ) {
-        add_pin_to_irq(irq, apic, pin);
-        vector = assign_irq_vector(irq, NULL);
-        if ( vector < 0 )
-            return vector;
+    if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR )
+    {
+        int vector = desc->arch.vector;
+
+        if ( vector < FIRST_HIPRIORITY_VECTOR )
+            add_pin_to_irq(irq, apic, pin);
+        else
+            desc->arch.vector = IRQ_VECTOR_UNASSIGNED;
+        ret = assign_irq_vector(irq, NULL);
+        if ( ret < 0 )
+        {
+            if ( vector < FIRST_HIPRIORITY_VECTOR )
+                remove_pin_from_irq(irq, apic, pin);
+            else
+                desc->arch.vector = vector;
+            return ret;
+        }
 
-        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", vector, irq);
+        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", ret, irq);
     }
     spin_lock(&dom0->event_lock);
     ret = map_domain_pirq(dom0, pirq, irq,




[-- Attachment #2: x86-ioapic-unused-hiprio-irq.patch --]
[-- Type: text/plain, Size: 3463 bytes --]

x86/IO-APIC: fix guest RTE write corner cases

This fixes two regressions from c/s 20143:a7de5bd776ca ("x86: Make the
hypercall PHYSDEVOP_alloc_irq_vector hypercall dummy"):

For one, IRQs that had their vector set up by Xen internally without a
handler ever having got set (e.g. via "com<n>=..." without a matching
consumer option like "console=com<n>") would wrongly call
add_pin_to_irq() here, triggering the BUG_ON() in that function.

Second, when assign_irq_vector() fails this addition to irq_2_pin[]
needs to be undone.

In the context of this I'm also surprised that the irq_2_pin[]
manipulations here occur without any lock, i.e. rely on Dom0 to do
some sort of serialization.

Signed-off-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/arch/x86/io_apic.c
+++ b/xen/arch/x86/io_apic.c
@@ -133,6 +133,37 @@ static void add_pin_to_irq(unsigned int 
     share_vector_maps(irq_2_pin[irq].apic, apic);
 }
 
+static void remove_pin_from_irq(unsigned int irq, int apic, int pin)
+{
+    struct irq_pin_list *entry, *prev;
+
+    for (entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next]) {
+        if ((entry->apic == apic) && (entry->pin == pin))
+            break;
+        BUG_ON(!entry->next);
+    }
+
+    entry->pin = entry->apic = -1;
+
+    if (entry != &irq_2_pin[irq]) {
+        /* Removed entry is not at head of list. */
+        prev = &irq_2_pin[irq];
+        while (&irq_2_pin[prev->next] != entry)
+            prev = &irq_2_pin[prev->next];
+        prev->next = entry->next;
+    } else if (entry->next) {
+        /* Removed entry is at head of multi-item list. */
+        prev  = entry;
+        entry = &irq_2_pin[entry->next];
+        *prev = *entry;
+        entry->pin = entry->apic = -1;
+    } else
+        return;
+
+    entry->next = irq_2_pin_free_entry;
+    irq_2_pin_free_entry = entry - irq_2_pin;
+}
+
 /*
  * Reroute an IRQ to a different pin.
  */
@@ -2280,7 +2311,7 @@ int ioapic_guest_read(unsigned long phys
 
 int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
 {
-    int apic, pin, irq, ret, vector, pirq;
+    int apic, pin, irq, ret, pirq;
     struct IO_APIC_route_entry rte = { 0 };
     unsigned long flags;
     struct irq_desc *desc;
@@ -2348,13 +2379,25 @@ int ioapic_guest_write(unsigned long phy
         return 0;
     }
 
-    if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR ) {
-        add_pin_to_irq(irq, apic, pin);
-        vector = assign_irq_vector(irq, NULL);
-        if ( vector < 0 )
-            return vector;
+    if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR )
+    {
+        int vector = desc->arch.vector;
+
+        if ( vector < FIRST_HIPRIORITY_VECTOR )
+            add_pin_to_irq(irq, apic, pin);
+        else
+            desc->arch.vector = IRQ_VECTOR_UNASSIGNED;
+        ret = assign_irq_vector(irq, NULL);
+        if ( ret < 0 )
+        {
+            if ( vector < FIRST_HIPRIORITY_VECTOR )
+                remove_pin_from_irq(irq, apic, pin);
+            else
+                desc->arch.vector = vector;
+            return ret;
+        }
 
-        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", vector, irq);
+        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", ret, irq);
     }
     spin_lock(&dom0->event_lock);
     ret = map_domain_pirq(dom0, pirq, irq,

[-- Attachment #3: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Ping: [PATCH] x86/IO-APIC: fix guest RTE write corner cases
  2013-05-08 12:51 [PATCH] x86/IO-APIC: fix guest RTE write corner cases Jan Beulich
@ 2013-05-14 14:52 ` Jan Beulich
  2013-05-14 15:17   ` Keir Fraser
                     ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Jan Beulich @ 2013-05-14 14:52 UTC (permalink / raw)
  To: Andrew Cooper, xiantao.zhang, Keir Fraser; +Cc: xen-devel

>>> On 08.05.13 at 14:51, "Jan Beulich" <JBeulich@suse.com> wrote:
> This fixes two regressions from c/s 20143:a7de5bd776ca ("x86: Make the
> hypercall PHYSDEVOP_alloc_irq_vector hypercall dummy"):
> 
> For one, IRQs that had their vector set up by Xen internally without a
> handler ever having got set (e.g. via "com<n>=..." without a matching
> consumer option like "console=com<n>") would wrongly call
> add_pin_to_irq() here, triggering the BUG_ON() in that function.
> 
> Second, when assign_irq_vector() fails this addition to irq_2_pin[]
> needs to be undone.
> 
> In the context of this I'm also surprised that the irq_2_pin[]
> manipulations here occur without any lock, i.e. rely on Dom0 to do
> some sort of serialization.
> 
> Signed-off-by: Jan Beulich <jbeulich@suse.com>

No-one having any opinion? I'm hesitant to commit changes like
this without anyone having said any word...

Jan

> --- a/xen/arch/x86/io_apic.c
> +++ b/xen/arch/x86/io_apic.c
> @@ -133,6 +133,37 @@ static void add_pin_to_irq(unsigned int 
>      share_vector_maps(irq_2_pin[irq].apic, apic);
>  }
>  
> +static void remove_pin_from_irq(unsigned int irq, int apic, int pin)
> +{
> +    struct irq_pin_list *entry, *prev;
> +
> +    for (entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next]) {
> +        if ((entry->apic == apic) && (entry->pin == pin))
> +            break;
> +        BUG_ON(!entry->next);
> +    }
> +
> +    entry->pin = entry->apic = -1;
> +
> +    if (entry != &irq_2_pin[irq]) {
> +        /* Removed entry is not at head of list. */
> +        prev = &irq_2_pin[irq];
> +        while (&irq_2_pin[prev->next] != entry)
> +            prev = &irq_2_pin[prev->next];
> +        prev->next = entry->next;
> +    } else if (entry->next) {
> +        /* Removed entry is at head of multi-item list. */
> +        prev  = entry;
> +        entry = &irq_2_pin[entry->next];
> +        *prev = *entry;
> +        entry->pin = entry->apic = -1;
> +    } else
> +        return;
> +
> +    entry->next = irq_2_pin_free_entry;
> +    irq_2_pin_free_entry = entry - irq_2_pin;
> +}
> +
>  /*
>   * Reroute an IRQ to a different pin.
>   */
> @@ -2280,7 +2311,7 @@ int ioapic_guest_read(unsigned long phys
>  
>  int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
>  {
> -    int apic, pin, irq, ret, vector, pirq;
> +    int apic, pin, irq, ret, pirq;
>      struct IO_APIC_route_entry rte = { 0 };
>      unsigned long flags;
>      struct irq_desc *desc;
> @@ -2348,13 +2379,25 @@ int ioapic_guest_write(unsigned long phy
>          return 0;
>      }
>  
> -    if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR ) {
> -        add_pin_to_irq(irq, apic, pin);
> -        vector = assign_irq_vector(irq, NULL);
> -        if ( vector < 0 )
> -            return vector;
> +    if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR )
> +    {
> +        int vector = desc->arch.vector;
> +
> +        if ( vector < FIRST_HIPRIORITY_VECTOR )
> +            add_pin_to_irq(irq, apic, pin);
> +        else
> +            desc->arch.vector = IRQ_VECTOR_UNASSIGNED;
> +        ret = assign_irq_vector(irq, NULL);
> +        if ( ret < 0 )
> +        {
> +            if ( vector < FIRST_HIPRIORITY_VECTOR )
> +                remove_pin_from_irq(irq, apic, pin);
> +            else
> +                desc->arch.vector = vector;
> +            return ret;
> +        }
>  
> -        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", vector, irq);
> +        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", ret, irq);
>      }
>      spin_lock(&dom0->event_lock);
>      ret = map_domain_pirq(dom0, pirq, irq,

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Ping: [PATCH] x86/IO-APIC: fix guest RTE write corner cases
  2013-05-14 14:52 ` Ping: " Jan Beulich
@ 2013-05-14 15:17   ` Keir Fraser
  2013-05-15 10:57   ` Andrew Cooper
  2013-05-16 12:47   ` Zhang, Xiantao
  2 siblings, 0 replies; 5+ messages in thread
From: Keir Fraser @ 2013-05-14 15:17 UTC (permalink / raw)
  To: Jan Beulich, Andrew Cooper, xiantao.zhang; +Cc: xen-devel

On 14/05/2013 15:52, "Jan Beulich" <JBeulich@suse.com> wrote:

>>>> On 08.05.13 at 14:51, "Jan Beulich" <JBeulich@suse.com> wrote:
>> This fixes two regressions from c/s 20143:a7de5bd776ca ("x86: Make the
>> hypercall PHYSDEVOP_alloc_irq_vector hypercall dummy"):
>> 
>> For one, IRQs that had their vector set up by Xen internally without a
>> handler ever having got set (e.g. via "com<n>=..." without a matching
>> consumer option like "console=com<n>") would wrongly call
>> add_pin_to_irq() here, triggering the BUG_ON() in that function.
>> 
>> Second, when assign_irq_vector() fails this addition to irq_2_pin[]
>> needs to be undone.
>> 
>> In the context of this I'm also surprised that the irq_2_pin[]
>> manipulations here occur without any lock, i.e. rely on Dom0 to do
>> some sort of serialization.
>> 
>> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> 
> No-one having any opinion? I'm hesitant to commit changes like
> this without anyone having said any word...

Yuk, well, the motivation is good and the code looks sane, so...
Acked-by: Keir Fraser <keir@xen.org>

> Jan
> 
>> --- a/xen/arch/x86/io_apic.c
>> +++ b/xen/arch/x86/io_apic.c
>> @@ -133,6 +133,37 @@ static void add_pin_to_irq(unsigned int
>>      share_vector_maps(irq_2_pin[irq].apic, apic);
>>  }
>>  
>> +static void remove_pin_from_irq(unsigned int irq, int apic, int pin)
>> +{
>> +    struct irq_pin_list *entry, *prev;
>> +
>> +    for (entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next]) {
>> +        if ((entry->apic == apic) && (entry->pin == pin))
>> +            break;
>> +        BUG_ON(!entry->next);
>> +    }
>> +
>> +    entry->pin = entry->apic = -1;
>> +
>> +    if (entry != &irq_2_pin[irq]) {
>> +        /* Removed entry is not at head of list. */
>> +        prev = &irq_2_pin[irq];
>> +        while (&irq_2_pin[prev->next] != entry)
>> +            prev = &irq_2_pin[prev->next];
>> +        prev->next = entry->next;
>> +    } else if (entry->next) {
>> +        /* Removed entry is at head of multi-item list. */
>> +        prev  = entry;
>> +        entry = &irq_2_pin[entry->next];
>> +        *prev = *entry;
>> +        entry->pin = entry->apic = -1;
>> +    } else
>> +        return;
>> +
>> +    entry->next = irq_2_pin_free_entry;
>> +    irq_2_pin_free_entry = entry - irq_2_pin;
>> +}
>> +
>>  /*
>>   * Reroute an IRQ to a different pin.
>>   */
>> @@ -2280,7 +2311,7 @@ int ioapic_guest_read(unsigned long phys
>>  
>>  int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
>>  {
>> -    int apic, pin, irq, ret, vector, pirq;
>> +    int apic, pin, irq, ret, pirq;
>>      struct IO_APIC_route_entry rte = { 0 };
>>      unsigned long flags;
>>      struct irq_desc *desc;
>> @@ -2348,13 +2379,25 @@ int ioapic_guest_write(unsigned long phy
>>          return 0;
>>      }
>>  
>> -    if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR )
>> {
>> -        add_pin_to_irq(irq, apic, pin);
>> -        vector = assign_irq_vector(irq, NULL);
>> -        if ( vector < 0 )
>> -            return vector;
>> +    if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR )
>> +    {
>> +        int vector = desc->arch.vector;
>> +
>> +        if ( vector < FIRST_HIPRIORITY_VECTOR )
>> +            add_pin_to_irq(irq, apic, pin);
>> +        else
>> +            desc->arch.vector = IRQ_VECTOR_UNASSIGNED;
>> +        ret = assign_irq_vector(irq, NULL);
>> +        if ( ret < 0 )
>> +        {
>> +            if ( vector < FIRST_HIPRIORITY_VECTOR )
>> +                remove_pin_from_irq(irq, apic, pin);
>> +            else
>> +                desc->arch.vector = vector;
>> +            return ret;
>> +        }
>>  
>> -        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", vector,
>> irq);
>> +        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", ret, irq);
>>      }
>>      spin_lock(&dom0->event_lock);
>>      ret = map_domain_pirq(dom0, pirq, irq,
> 
> 
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Ping: [PATCH] x86/IO-APIC: fix guest RTE write corner cases
  2013-05-14 14:52 ` Ping: " Jan Beulich
  2013-05-14 15:17   ` Keir Fraser
@ 2013-05-15 10:57   ` Andrew Cooper
  2013-05-16 12:47   ` Zhang, Xiantao
  2 siblings, 0 replies; 5+ messages in thread
From: Andrew Cooper @ 2013-05-15 10:57 UTC (permalink / raw)
  To: Jan Beulich; +Cc: Keir (Xen.org), xiantao.zhang@intel.com, xen-devel

On 14/05/13 15:52, Jan Beulich wrote:
>>>> On 08.05.13 at 14:51, "Jan Beulich" <JBeulich@suse.com> wrote:
>> This fixes two regressions from c/s 20143:a7de5bd776ca ("x86: Make the
>> hypercall PHYSDEVOP_alloc_irq_vector hypercall dummy"):
>>
>> For one, IRQs that had their vector set up by Xen internally without a
>> handler ever having got set (e.g. via "com<n>=..." without a matching
>> consumer option like "console=com<n>") would wrongly call
>> add_pin_to_irq() here, triggering the BUG_ON() in that function.
>>
>> Second, when assign_irq_vector() fails this addition to irq_2_pin[]
>> needs to be undone.
>>
>> In the context of this I'm also surprised that the irq_2_pin[]
>> manipulations here occur without any lock, i.e. rely on Dom0 to do
>> some sort of serialization.
>>
>> Signed-off-by: Jan Beulich <jbeulich@suse.com>
> No-one having any opinion? I'm hesitant to commit changes like
> this without anyone having said any word...
>
> Jan

Sorry - this was on my list to look at but I have been very busy recently.

It tentatively looks good to me.

~Andrew

>
>> --- a/xen/arch/x86/io_apic.c
>> +++ b/xen/arch/x86/io_apic.c
>> @@ -133,6 +133,37 @@ static void add_pin_to_irq(unsigned int 
>>      share_vector_maps(irq_2_pin[irq].apic, apic);
>>  }
>>  
>> +static void remove_pin_from_irq(unsigned int irq, int apic, int pin)
>> +{
>> +    struct irq_pin_list *entry, *prev;
>> +
>> +    for (entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next]) {
>> +        if ((entry->apic == apic) && (entry->pin == pin))
>> +            break;
>> +        BUG_ON(!entry->next);
>> +    }
>> +
>> +    entry->pin = entry->apic = -1;
>> +
>> +    if (entry != &irq_2_pin[irq]) {
>> +        /* Removed entry is not at head of list. */
>> +        prev = &irq_2_pin[irq];
>> +        while (&irq_2_pin[prev->next] != entry)
>> +            prev = &irq_2_pin[prev->next];
>> +        prev->next = entry->next;
>> +    } else if (entry->next) {
>> +        /* Removed entry is at head of multi-item list. */
>> +        prev  = entry;
>> +        entry = &irq_2_pin[entry->next];
>> +        *prev = *entry;
>> +        entry->pin = entry->apic = -1;
>> +    } else
>> +        return;
>> +
>> +    entry->next = irq_2_pin_free_entry;
>> +    irq_2_pin_free_entry = entry - irq_2_pin;
>> +}
>> +
>>  /*
>>   * Reroute an IRQ to a different pin.
>>   */
>> @@ -2280,7 +2311,7 @@ int ioapic_guest_read(unsigned long phys
>>  
>>  int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
>>  {
>> -    int apic, pin, irq, ret, vector, pirq;
>> +    int apic, pin, irq, ret, pirq;
>>      struct IO_APIC_route_entry rte = { 0 };
>>      unsigned long flags;
>>      struct irq_desc *desc;
>> @@ -2348,13 +2379,25 @@ int ioapic_guest_write(unsigned long phy
>>          return 0;
>>      }
>>  
>> -    if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR ) {
>> -        add_pin_to_irq(irq, apic, pin);
>> -        vector = assign_irq_vector(irq, NULL);
>> -        if ( vector < 0 )
>> -            return vector;
>> +    if ( desc->arch.vector <= 0 || desc->arch.vector > LAST_DYNAMIC_VECTOR )
>> +    {
>> +        int vector = desc->arch.vector;
>> +
>> +        if ( vector < FIRST_HIPRIORITY_VECTOR )
>> +            add_pin_to_irq(irq, apic, pin);
>> +        else
>> +            desc->arch.vector = IRQ_VECTOR_UNASSIGNED;
>> +        ret = assign_irq_vector(irq, NULL);
>> +        if ( ret < 0 )
>> +        {
>> +            if ( vector < FIRST_HIPRIORITY_VECTOR )
>> +                remove_pin_from_irq(irq, apic, pin);
>> +            else
>> +                desc->arch.vector = vector;
>> +            return ret;
>> +        }
>>  
>> -        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", vector, irq);
>> +        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", ret, irq);
>>      }
>>      spin_lock(&dom0->event_lock);
>>      ret = map_domain_pirq(dom0, pirq, irq,
>
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Ping: [PATCH] x86/IO-APIC: fix guest RTE write corner cases
  2013-05-14 14:52 ` Ping: " Jan Beulich
  2013-05-14 15:17   ` Keir Fraser
  2013-05-15 10:57   ` Andrew Cooper
@ 2013-05-16 12:47   ` Zhang, Xiantao
  2 siblings, 0 replies; 5+ messages in thread
From: Zhang, Xiantao @ 2013-05-16 12:47 UTC (permalink / raw)
  To: Jan Beulich, Andrew Cooper, Keir Fraser; +Cc: Zhang, Xiantao, xen-devel

Looks fine to me. Acked, Thanks! 
Xiantao

> -----Original Message-----
> From: Jan Beulich [mailto:JBeulich@suse.com]
> Sent: Tuesday, May 14, 2013 10:52 PM
> To: Andrew Cooper; Zhang, Xiantao; Keir Fraser
> Cc: xen-devel
> Subject: Ping: [PATCH] x86/IO-APIC: fix guest RTE write corner cases
> 
> >>> On 08.05.13 at 14:51, "Jan Beulich" <JBeulich@suse.com> wrote:
> > This fixes two regressions from c/s 20143:a7de5bd776ca ("x86: Make the
> > hypercall PHYSDEVOP_alloc_irq_vector hypercall dummy"):
> >
> > For one, IRQs that had their vector set up by Xen internally without a
> > handler ever having got set (e.g. via "com<n>=..." without a matching
> > consumer option like "console=com<n>") would wrongly call
> > add_pin_to_irq() here, triggering the BUG_ON() in that function.
> >
> > Second, when assign_irq_vector() fails this addition to irq_2_pin[]
> > needs to be undone.
> >
> > In the context of this I'm also surprised that the irq_2_pin[]
> > manipulations here occur without any lock, i.e. rely on Dom0 to do
> > some sort of serialization.
> >
> > Signed-off-by: Jan Beulich <jbeulich@suse.com>
> 
> No-one having any opinion? I'm hesitant to commit changes like
> this without anyone having said any word...
> 
> Jan
> 
> > --- a/xen/arch/x86/io_apic.c
> > +++ b/xen/arch/x86/io_apic.c
> > @@ -133,6 +133,37 @@ static void add_pin_to_irq(unsigned int
> >      share_vector_maps(irq_2_pin[irq].apic, apic);
> >  }
> >
> > +static void remove_pin_from_irq(unsigned int irq, int apic, int pin)
> > +{
> > +    struct irq_pin_list *entry, *prev;
> > +
> > +    for (entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next]) {
> > +        if ((entry->apic == apic) && (entry->pin == pin))
> > +            break;
> > +        BUG_ON(!entry->next);
> > +    }
> > +
> > +    entry->pin = entry->apic = -1;
> > +
> > +    if (entry != &irq_2_pin[irq]) {
> > +        /* Removed entry is not at head of list. */
> > +        prev = &irq_2_pin[irq];
> > +        while (&irq_2_pin[prev->next] != entry)
> > +            prev = &irq_2_pin[prev->next];
> > +        prev->next = entry->next;
> > +    } else if (entry->next) {
> > +        /* Removed entry is at head of multi-item list. */
> > +        prev  = entry;
> > +        entry = &irq_2_pin[entry->next];
> > +        *prev = *entry;
> > +        entry->pin = entry->apic = -1;
> > +    } else
> > +        return;
> > +
> > +    entry->next = irq_2_pin_free_entry;
> > +    irq_2_pin_free_entry = entry - irq_2_pin;
> > +}
> > +
> >  /*
> >   * Reroute an IRQ to a different pin.
> >   */
> > @@ -2280,7 +2311,7 @@ int ioapic_guest_read(unsigned long phys
> >
> >  int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
> >  {
> > -    int apic, pin, irq, ret, vector, pirq;
> > +    int apic, pin, irq, ret, pirq;
> >      struct IO_APIC_route_entry rte = { 0 };
> >      unsigned long flags;
> >      struct irq_desc *desc;
> > @@ -2348,13 +2379,25 @@ int ioapic_guest_write(unsigned long phy
> >          return 0;
> >      }
> >
> > -    if ( desc->arch.vector <= 0 || desc->arch.vector >
> LAST_DYNAMIC_VECTOR ) {
> > -        add_pin_to_irq(irq, apic, pin);
> > -        vector = assign_irq_vector(irq, NULL);
> > -        if ( vector < 0 )
> > -            return vector;
> > +    if ( desc->arch.vector <= 0 || desc->arch.vector >
> LAST_DYNAMIC_VECTOR )
> > +    {
> > +        int vector = desc->arch.vector;
> > +
> > +        if ( vector < FIRST_HIPRIORITY_VECTOR )
> > +            add_pin_to_irq(irq, apic, pin);
> > +        else
> > +            desc->arch.vector = IRQ_VECTOR_UNASSIGNED;
> > +        ret = assign_irq_vector(irq, NULL);
> > +        if ( ret < 0 )
> > +        {
> > +            if ( vector < FIRST_HIPRIORITY_VECTOR )
> > +                remove_pin_from_irq(irq, apic, pin);
> > +            else
> > +                desc->arch.vector = vector;
> > +            return ret;
> > +        }
> >
> > -        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", vector, irq);
> > +        printk(XENLOG_INFO "allocated vector %02x for irq %d\n", ret, irq);
> >      }
> >      spin_lock(&dom0->event_lock);
> >      ret = map_domain_pirq(dom0, pirq, irq,
> 
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-05-16 12:47 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-08 12:51 [PATCH] x86/IO-APIC: fix guest RTE write corner cases Jan Beulich
2013-05-14 14:52 ` Ping: " Jan Beulich
2013-05-14 15:17   ` Keir Fraser
2013-05-15 10:57   ` Andrew Cooper
2013-05-16 12:47   ` Zhang, Xiantao

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.