# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1244109126 -3600
# Node ID 2e0834d5e01d6231753bd39849bf578670fb84de
# Parent 75a24d7db2819f214ebebcea57bb7c8262190241
vtd: Fix apic pin to interrupt remapping table index
Originally, it calls xmalloc to set index in
ioapic_rte_to_remap_entry(). When make with debug=y, it may trigger
spinlock BUG_ON because allocate memory with interrupt disabled.
Signed-off-by: Weidong Han <weidong.han@xxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset: 19707:07cf79dfb59c
xen-unstable date: Wed Jun 03 12:59:44 2009 +0100
vtd: ia64 fix of intremap.c
19707:07cf79dfb59c caused compilation error on ia64.
This patch fixes it.
Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
xen-unstable changeset: 19727:abdd365e2ec3
xen-unstable date: Thu Jun 04 10:48:45 2009 +0100
---
xen/arch/ia64/linux-xen/iosapic.c | 18 ++++
xen/drivers/passthrough/vtd/intremap.c | 110 +++++++++------------------
xen/include/asm-ia64/linux-xen/asm/iosapic.h | 3
3 files changed, 61 insertions(+), 70 deletions(-)
diff -r 75a24d7db281 -r 2e0834d5e01d xen/arch/ia64/linux-xen/iosapic.c
--- a/xen/arch/ia64/linux-xen/iosapic.c Wed Jun 03 15:16:49 2009 +0100
+++ b/xen/arch/ia64/linux-xen/iosapic.c Thu Jun 04 10:52:06 2009 +0100
@@ -1275,4 +1275,22 @@ int iosapic_guest_write(unsigned long ph
spin_unlock_irqrestore(&irq_descp(vec)->lock, flags);
return 0;
}
+
+/* for vtd interrupt remapping. xen/drivers/vtd/intremap.c */
+int iosapic_get_nr_iosapics(void)
+{
+ int index;
+
+ for (index = NR_IOSAPICS - 1; index >= 0; index--) {
+ if (iosapic_lists[index].addr)
+ break;
+ }
+
+ return index + 1;
+}
+
+int iosapic_get_nr_pins(int index)
+{
+ return iosapic_lists[index].num_rte;
+}
#endif /* XEN */
diff -r 75a24d7db281 -r 2e0834d5e01d xen/drivers/passthrough/vtd/intremap.c
--- a/xen/drivers/passthrough/vtd/intremap.c Wed Jun 03 15:16:49 2009 +0100
+++ b/xen/drivers/passthrough/vtd/intremap.c Thu Jun 04 10:52:06 2009 +0100
@@ -31,71 +31,44 @@
#include "vtd.h"
#include "extern.h"
-#ifndef dest_SMI
+#ifdef __ia64__
#define dest_SMI -1
+#define nr_ioapics iosapic_get_nr_iosapics()
+#define nr_ioapic_registers(i) iosapic_get_nr_pins(i)
+#else
+#define nr_ioapic_registers(i) nr_ioapic_registers[i]
#endif
-/* The max number of IOAPIC (or IOSAPIC) pin. The typical values can be 24 or
- * 48 on x86 and Itanium platforms. Here we use a biger number 256. This
- * should be big enough. Actually now IREMAP_ENTRY_NR is also 256.
- */
-#define MAX_IOAPIC_PIN_NUM 256
-
-struct ioapicid_pin_intremap_index {
- struct list_head list;
- unsigned int ioapic_id;
- unsigned int pin;
- int intremap_index;
-};
-
-static struct list_head ioapic_pin_to_intremap_index[MAX_IOAPIC_PIN_NUM];
-
-static int init_ioapic_pin_intremap_index(void)
-{
- static int initialized = 0;
- int i;
-
- if ( initialized == 1 )
- return 0;
-
- for ( i = 0; i < MAX_IOAPIC_PIN_NUM; i++ )
- INIT_LIST_HEAD(&ioapic_pin_to_intremap_index[i]);
-
- initialized = 1;
- return 0;
-}
-
-static int get_ioapic_pin_intremap_index(unsigned int ioapic_id,
- unsigned int pin)
-{
- struct ioapicid_pin_intremap_index *entry;
- struct list_head *pos, *tmp;
-
- list_for_each_safe ( pos, tmp, &ioapic_pin_to_intremap_index[pin] )
- {
- entry = list_entry(pos, struct ioapicid_pin_intremap_index, list);
- if ( entry->ioapic_id == ioapic_id )
- return entry->intremap_index;
- }
-
- return -1;
-}
-
-static int set_ioapic_pin_intremap_index(unsigned int ioapic_id,
- unsigned int pin,
- int index)
-{
- struct ioapicid_pin_intremap_index *entry;
-
- entry = xmalloc(struct ioapicid_pin_intremap_index);
- if ( !entry )
+/* apic_pin_2_ir_idx[apicid][pin] = interrupt remapping table index */
+static unsigned int **apic_pin_2_ir_idx;
+
+static int init_apic_pin_2_ir_idx(void)
+{
+ unsigned int *_apic_pin_2_ir_idx;
+ unsigned int nr_pins, i;
+
+ nr_pins = 0;
+ for ( i = 0; i < nr_ioapics; i++ )
+ nr_pins += nr_ioapic_registers(i);
+
+ _apic_pin_2_ir_idx = xmalloc_array(unsigned int, nr_pins);
+ apic_pin_2_ir_idx = xmalloc_array(unsigned int *, nr_ioapics);
+ if ( (_apic_pin_2_ir_idx == NULL) || (apic_pin_2_ir_idx == NULL) )
+ {
+ xfree(_apic_pin_2_ir_idx);
+ xfree(apic_pin_2_ir_idx);
return -ENOMEM;
-
- entry->ioapic_id = ioapic_id;
- entry->pin = pin;
- entry->intremap_index = index;
-
- list_add_tail(&entry->list, &ioapic_pin_to_intremap_index[pin]);
+ }
+
+ for ( i = 0; i < nr_pins; i++ )
+ _apic_pin_2_ir_idx[i] = -1;
+
+ nr_pins = 0;
+ for ( i = 0; i < nr_ioapics; i++ )
+ {
+ apic_pin_2_ir_idx[i] = &_apic_pin_2_ir_idx[nr_pins];
+ nr_pins += nr_ioapic_registers(i);
+ }
return 0;
}
@@ -160,7 +133,7 @@ static int remap_entry_to_ioapic_rte(
}
static int ioapic_rte_to_remap_entry(struct iommu *iommu,
- int apic_id, unsigned int ioapic_pin, struct IO_xAPIC_route_entry *old_rte,
+ int apic, unsigned int ioapic_pin, struct IO_xAPIC_route_entry *old_rte,
unsigned int rte_upper, unsigned int value)
{
struct iremap_entry *iremap_entry = NULL, *iremap_entries;
@@ -174,12 +147,12 @@ static int ioapic_rte_to_remap_entry(str
remap_rte = (struct IO_APIC_route_remap_entry *) old_rte;
spin_lock_irqsave(&ir_ctrl->iremap_lock, flags);
- index = get_ioapic_pin_intremap_index(apic_id, ioapic_pin);
+ index = apic_pin_2_ir_idx[apic][ioapic_pin];
if ( index < 0 )
{
ir_ctrl->iremap_index++;
index = ir_ctrl->iremap_index;
- set_ioapic_pin_intremap_index(apic_id, ioapic_pin, index);
+ apic_pin_2_ir_idx[apic][ioapic_pin] = index;
}
if ( index > IREMAP_ENTRY_NR - 1 )
@@ -218,7 +191,7 @@ static int ioapic_rte_to_remap_entry(str
new_ire.lo.res_1 = 0;
new_ire.lo.vector = new_rte.vector;
new_ire.lo.res_2 = 0;
- new_ire.hi.sid = apicid_to_bdf(apic_id);
+ new_ire.hi.sid = apicid_to_bdf(IO_APIC_ID(apic));
new_ire.hi.sq = 0; /* comparing all 16-bit of SID */
new_ire.hi.svt = 1; /* requestor ID verification SID/SQ */
@@ -356,8 +329,7 @@ void io_apic_write_remap_rte(
*(IO_APIC_BASE(apic)+4) = *(((int *)&old_rte)+0);
remap_rte->mask = saved_mask;
- ASSERT(ioapic_pin < MAX_IOAPIC_PIN_NUM);
- if ( ioapic_rte_to_remap_entry(iommu, IO_APIC_ID(apic), ioapic_pin,
+ if ( ioapic_rte_to_remap_entry(iommu, apic, ioapic_pin,
&old_rte, rte_upper, value) )
{
*IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg;
@@ -628,9 +600,7 @@ int enable_intremap(struct iommu *iommu)
/* After set SIRTP, we should do globally invalidate the IEC */
iommu_flush_iec_global(iommu);
- init_ioapic_pin_intremap_index();
-
- return 0;
+ return init_apic_pin_2_ir_idx();
}
void disable_intremap(struct iommu *iommu)
diff -r 75a24d7db281 -r 2e0834d5e01d
xen/include/asm-ia64/linux-xen/asm/iosapic.h
--- a/xen/include/asm-ia64/linux-xen/asm/iosapic.h Wed Jun 03 15:16:49
2009 +0100
+++ b/xen/include/asm-ia64/linux-xen/asm/iosapic.h Thu Jun 04 10:52:06
2009 +0100
@@ -186,6 +186,9 @@ struct rte_entry {
#define IOSAPIC_RTEINDEX(reg) (((reg) - 0x10) >> 1)
extern unsigned long ia64_vector_mask[];
extern unsigned long ia64_xen_vector[];
+
+int iosapic_get_nr_iosapics(void);
+int iosapic_get_nr_pins(int index);
#endif /* XEN */
#define IO_APIC_BASE(idx) ((unsigned int *)iosapic_lists[idx].addr)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|