ac6e56e6d7
23900-xzalloc.patch 24144-cpufreq-turbo-crash.patch 24148-shadow-pgt-dying-op-performance.patch 24155-x86-ioapic-EOI-after-migration.patch 24156-x86-ioapic-shared-vectors.patch 24157-x86-xstate-init.patch 24168-x86-vioapic-clear-remote_irr.patch - submit fixes for bnc#649209 and bnc#711892 xl-create-pv-with-qcow2-img.patch update suspend_evtchn_lock.patch - Update trace.c, merge patches from upstream 23050-xentrace_dynamic_tracebuffer_allocation.patch 23091-xentrace_fix_t_info_pages_calculation..patch 23092-xentrace_print_calculated_numbers_in_calculate_tbuf_size.patch 23093-xentrace_remove_gdprintk_usage_since_they_are_not_in_guest_context.patch 23094-xentrace_update_comments.patch 23095-xentrace_use_consistent_printk_prefix.patch 23128-xentrace_correct_formula_to_calculate_t_info_pages.patch 23129-xentrace_remove_unneeded_debug_printk.patch 23173-xentrace_Move_register_cpu_notifier_call_into_boot-time_init..patch 23239-xentrace_correct_overflow_check_for_number_of_per-cpu_trace_pages.patch 23308-xentrace_Move_the_global_variable_t_info_first_offset_into_calculate_tbuf_size.patch 23309-xentrace_Mark_data_size___read_mostly_because_its_only_written_once.patch 23310-xentrace_Remove_unneeded_cast_when_assigning_pointer_value_to_dst.patch 23404-xentrace_reduce_trace_buffer_size_to_something_mfn_offset_can_reach.patch OBS-URL: https://build.opensuse.org/package/show/Virtualization/xen?expand=0&rev=160
160 lines
4.9 KiB
Diff
160 lines
4.9 KiB
Diff
References: bnc#713503
|
|
|
|
# HG changeset patch
|
|
# User Jan Beulich <jbeulich@suse.com>
|
|
# Date 1321604484 -3600
|
|
# Node ID f29b5bd6e25fd78409baa5461914c67065f7579f
|
|
# Parent 0d50e704834fb53c6c86b8b0badd19d88e73c4ed
|
|
x86/IRQ: prevent vector sharing within IO-APICs
|
|
|
|
Following the prevention of vector sharing for MSIs, this change
|
|
enforces the same within IO-APICs: Pin based interrupts use the IO-APIC
|
|
as their identifying device under the AMD IOMMU (and just like for
|
|
MSIs, only the identifying device is used to remap interrupts here,
|
|
with no regard to an interrupt's destination).
|
|
|
|
Additionally, LAPIC initiated EOIs (for level triggered interrupts) too
|
|
use only the vector for identifying which interrupts to end. While this
|
|
generally causes no significant problem (at worst an interrupt would be
|
|
re-raised without a new interrupt event actually having occurred), it
|
|
still seems better to avoid the situation.
|
|
|
|
For this second aspect, a distinction is being made between the
|
|
traditional and the directed-EOI cases: In the former, vectors should
|
|
not be shared throughout all IO-APICs in the system, while in the
|
|
latter case only individual IO-APICs need to be contrained (or, if the
|
|
firmware indicates so, sub- groups of them having the same GSI appear
|
|
at multiple pins).
|
|
|
|
Signed-off-by: Jan Beulich <jbeulich@suse.com>
|
|
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
|
|
|
|
--- a/xen/arch/x86/io_apic.c
|
|
+++ b/xen/arch/x86/io_apic.c
|
|
@@ -69,6 +69,34 @@ int __read_mostly nr_ioapics;
|
|
|
|
#define ioapic_has_eoi_reg(apic) (mp_ioapics[(apic)].mpc_apicver >= 0x20)
|
|
|
|
+static int apic_pin_2_gsi_irq(int apic, int pin);
|
|
+
|
|
+static vmask_t *__read_mostly vector_map[MAX_IO_APICS];
|
|
+
|
|
+static void share_vector_maps(unsigned int src, unsigned int dst)
|
|
+{
|
|
+ unsigned int pin;
|
|
+
|
|
+ if (vector_map[src] == vector_map[dst])
|
|
+ return;
|
|
+
|
|
+ bitmap_or(vector_map[src]->_bits, vector_map[src]->_bits,
|
|
+ vector_map[dst]->_bits, NR_VECTORS);
|
|
+
|
|
+ for (pin = 0; pin < nr_ioapic_registers[dst]; ++pin) {
|
|
+ int irq = apic_pin_2_gsi_irq(dst, pin);
|
|
+ struct irq_cfg *cfg;
|
|
+
|
|
+ if (irq < 0)
|
|
+ continue;
|
|
+ cfg = irq_cfg(irq);
|
|
+ if (cfg->used_vectors == vector_map[dst])
|
|
+ cfg->used_vectors = vector_map[src];
|
|
+ }
|
|
+
|
|
+ vector_map[dst] = vector_map[src];
|
|
+}
|
|
+
|
|
/*
|
|
* This is performance-critical, we want to do it O(1)
|
|
*
|
|
@@ -109,6 +137,7 @@ static void add_pin_to_irq(unsigned int
|
|
}
|
|
entry->apic = apic;
|
|
entry->pin = pin;
|
|
+ share_vector_maps(irq_2_pin[irq].apic, apic);
|
|
}
|
|
|
|
/*
|
|
@@ -124,6 +153,7 @@ static void __init replace_pin_at_irq(un
|
|
if (entry->apic == oldapic && entry->pin == oldpin) {
|
|
entry->apic = newapic;
|
|
entry->pin = newpin;
|
|
+ share_vector_maps(oldapic, newapic);
|
|
}
|
|
if (!entry->next)
|
|
break;
|
|
@@ -131,6 +161,16 @@ static void __init replace_pin_at_irq(un
|
|
}
|
|
}
|
|
|
|
+vmask_t *io_apic_get_used_vector_map(unsigned int irq)
|
|
+{
|
|
+ struct irq_pin_list *entry = irq_2_pin + irq;
|
|
+
|
|
+ if (entry->pin == -1)
|
|
+ return NULL;
|
|
+
|
|
+ return vector_map[entry->apic];
|
|
+}
|
|
+
|
|
struct IO_APIC_route_entry **alloc_ioapic_entries(void)
|
|
{
|
|
int apic;
|
|
@@ -1314,6 +1354,18 @@ static void __init enable_IO_APIC(void)
|
|
for (i = irq_2_pin_free_entry = nr_irqs_gsi; i < PIN_MAP_SIZE; i++)
|
|
irq_2_pin[i].next = i + 1;
|
|
|
|
+ if (directed_eoi_enabled) {
|
|
+ for (apic = 0; apic < nr_ioapics; apic++) {
|
|
+ vector_map[apic] = xzalloc(vmask_t);
|
|
+ BUG_ON(!vector_map[apic]);
|
|
+ }
|
|
+ } else {
|
|
+ vector_map[0] = xzalloc(vmask_t);
|
|
+ BUG_ON(!vector_map[0]);
|
|
+ for (apic = 1; apic < nr_ioapics; apic++)
|
|
+ vector_map[apic] = vector_map[0];
|
|
+ }
|
|
+
|
|
for(apic = 0; apic < nr_ioapics; apic++) {
|
|
int pin;
|
|
/* See if any of the pins is in ExtINT mode */
|
|
@@ -2479,13 +2531,12 @@ int ioapic_guest_write(unsigned long phy
|
|
}
|
|
|
|
if ( cfg->vector <= 0 || cfg->vector > LAST_DYNAMIC_VECTOR ) {
|
|
+ add_pin_to_irq(irq, apic, pin);
|
|
vector = assign_irq_vector(irq);
|
|
if ( vector < 0 )
|
|
return vector;
|
|
|
|
printk(XENLOG_INFO "allocated vector %02x for irq %d\n", vector, irq);
|
|
-
|
|
- add_pin_to_irq(irq, apic, pin);
|
|
}
|
|
spin_lock(&pcidevs_lock);
|
|
spin_lock(&dom0->event_lock);
|
|
--- a/xen/arch/x86/irq.c
|
|
+++ b/xen/arch/x86/irq.c
|
|
@@ -403,6 +403,11 @@ static vmask_t *irq_get_used_vector_mask
|
|
}
|
|
}
|
|
}
|
|
+ else if ( IO_APIC_IRQ(irq) &&
|
|
+ opt_irq_vector_map != OPT_IRQ_VECTOR_MAP_NONE )
|
|
+ {
|
|
+ ret = io_apic_get_used_vector_map(irq);
|
|
+ }
|
|
|
|
return ret;
|
|
}
|
|
--- a/xen/include/asm-x86/irq.h
|
|
+++ b/xen/include/asm-x86/irq.h
|
|
@@ -113,6 +113,7 @@ void setup_IO_APIC(void);
|
|
void disable_IO_APIC(void);
|
|
void print_IO_APIC(void);
|
|
void setup_ioapic_dest(void);
|
|
+vmask_t *io_apic_get_used_vector_map(unsigned int irq);
|
|
|
|
extern unsigned long io_apic_irqs;
|
|
|