@@ -23,6 +23,7 @@
#include <xen/sched.h>
#include <xen/irq.h>
#include <xen/keyhandler.h>
+#include <asm/io_apic.h>
#include <asm/hvm/domain.h>
#include <asm/hvm/support.h>
#include <asm/msi.h>
@@ -212,12 +213,25 @@ void hvm_gsi_deassert(struct domain *d, unsigned int gsi)
spin_unlock(&d->arch.hvm.irq_lock);
}
+unsigned int hvm_isa_irq_to_gsi(const struct domain *d, unsigned int irq)
+{
+ int pin, apic;
+
+ if ( !is_hardware_domain(d) )
+ return irq ?: 2;
+
+ pin = io_apic_find_isa_irq_pin(irq, mp_INT);
+ apic = io_apic_find_isa_irq_apic(irq, mp_INT);
+
+ return (pin < 0 || apic < 0) ? irq : (io_apic_gsi_base(apic) + pin);
+}
+
int hvm_isa_irq_assert(struct domain *d, unsigned int isa_irq,
int (*get_vector)(const struct domain *d,
unsigned int gsi))
{
struct hvm_irq *hvm_irq = hvm_domain_irq(d);
- unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
+ unsigned int gsi = hvm_isa_irq_to_gsi(d, isa_irq);
int vector = -1;
ASSERT(isa_irq <= 15);
@@ -240,7 +254,7 @@ void hvm_isa_irq_deassert(
struct domain *d, unsigned int isa_irq)
{
struct hvm_irq *hvm_irq = hvm_domain_irq(d);
- unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
+ unsigned int gsi = hvm_isa_irq_to_gsi(d, isa_irq);
ASSERT(isa_irq <= 15);
@@ -754,7 +768,7 @@ static int irq_load_isa(struct domain *d, hvm_domain_context_t *h)
* This relies on the PCI IRQ state being loaded first. */
for ( irq = 0; platform_legacy_irq(irq); irq++ )
if ( test_bit(irq, &hvm_irq->isa_irq.i) )
- hvm_irq->gsi_assert_count[hvm_isa_irq_to_gsi(irq)]++;
+ hvm_irq->gsi_assert_count[hvm_isa_irq_to_gsi(d, irq)]++;
return 0;
}
@@ -425,7 +425,7 @@ static void vioapic_deliver(struct hvm_vioapic *vioapic, unsigned int pin)
struct vlapic *lapic0 = vcpu_vlapic(d->vcpu[0]);
/* Force to pick vCPU 0 if part of the destination list */
- if ( (irq == hvm_isa_irq_to_gsi(0)) && pit_channel0_enabled() &&
+ if ( (irq == hvm_isa_irq_to_gsi(d, 0)) && pit_channel0_enabled() &&
vlapic_match_dest(lapic0, NULL, 0, dest, dest_mode) &&
vlapic_enabled(lapic0) )
target = lapic0;
@@ -230,6 +230,8 @@ static void vpic_ioport_write(
}
else
{
+ struct domain *currd = current->domain;
+
/* OCW2 */
cmd = val >> 5;
switch ( cmd )
@@ -260,8 +262,9 @@ static void vpic_ioport_write(
/* Release lock and EOI the physical interrupt (if any). */
vpic_update_int_output(vpic);
vpic_unlock(vpic);
- hvm_dpci_eoi(current->domain,
- hvm_isa_irq_to_gsi((addr >> 7) ? (irq|8) : irq),
+ hvm_dpci_eoi(currd,
+ hvm_isa_irq_to_gsi(currd, (addr >> 7) ? (irq | 8)
+ : irq),
NULL);
return; /* bail immediately */
case 6: /* Set Priority */
@@ -86,7 +86,8 @@ static int pt_irq_vector(struct periodic_time *pt, enum hvm_intsrc src)
return pt->irq;
isa_irq = pt->irq;
- gsi = pt->source == PTSRC_isa ? hvm_isa_irq_to_gsi(isa_irq) : pt->irq;
+ gsi = pt->source == PTSRC_isa ? hvm_isa_irq_to_gsi(v->domain, isa_irq)
+ : pt->irq;
if ( src == hvm_intsrc_pic )
return (v->domain->arch.hvm.vpic[isa_irq >> 3].irq_base
@@ -128,7 +129,7 @@ static int pt_irq_masked(struct periodic_time *pt)
if ( !(pic_imr & (1 << (pt->irq & 7))) && vlapic_accept_pic_intr(v) )
return 0;
- gsi = hvm_isa_irq_to_gsi(pt->irq);
+ gsi = hvm_isa_irq_to_gsi(v->domain, pt->irq);
}
/* Fallthrough to check if the interrupt is masked on the IO APIC. */
@@ -608,7 +608,7 @@ static int find_irq_entry(int apic, int pin, int type)
/*
* Find the pin to which IRQ[irq] (ISA) is connected
*/
-static int __init find_isa_irq_pin(int irq, int type)
+int io_apic_find_isa_irq_pin(int irq, int type)
{
int i;
@@ -628,7 +628,7 @@ static int __init find_isa_irq_pin(int irq, int type)
return -1;
}
-static int __init find_isa_irq_apic(int irq, int type)
+int io_apic_find_isa_irq_apic(int irq, int type)
{
int i;
@@ -1306,8 +1306,8 @@ static void __init enable_IO_APIC(void)
* the i8259 probably is not connected the ioapic but give the
* mptable a chance anyway.
*/
- i8259_pin = find_isa_irq_pin(0, mp_ExtINT);
- i8259_apic = find_isa_irq_apic(0, mp_ExtINT);
+ i8259_pin = io_apic_find_isa_irq_pin(0, mp_ExtINT);
+ i8259_apic = io_apic_find_isa_irq_apic(0, mp_ExtINT);
/* Trust the MP table if nothing is setup in the hardware */
if ((ioapic_i8259.pin == -1) && (i8259_pin >= 0)) {
printk(KERN_WARNING "ExtINT not setup in hardware but reported by MP table\n");
@@ -1834,8 +1834,8 @@ static void __init unlock_ExtINT_logic(void)
struct IO_APIC_route_entry entry0, entry1;
unsigned char save_control, save_freq_select;
- pin = find_isa_irq_pin(8, mp_INT);
- apic = find_isa_irq_apic(8, mp_INT);
+ pin = io_apic_find_isa_irq_pin(8, mp_INT);
+ apic = io_apic_find_isa_irq_apic(8, mp_INT);
if ( pin == -1 || apic == -1 )
return;
@@ -1913,8 +1913,8 @@ static void __init check_timer(void)
/*timer_ack = 1;*/
/*enable_8259A_irq(irq_to_desc(0));*/
- pin1 = find_isa_irq_pin(0, mp_INT);
- apic1 = find_isa_irq_apic(0, mp_INT);
+ pin1 = io_apic_find_isa_irq_pin(0, mp_INT);
+ apic1 = io_apic_find_isa_irq_apic(0, mp_INT);
pin2 = ioapic_i8259.pin;
apic2 = ioapic_i8259.apic;
@@ -100,7 +100,7 @@ struct hvm_irq {
#define hvm_domain_irq(d) ((d)->arch.hvm.irq)
#define hvm_irq_size(cnt) offsetof(struct hvm_irq, gsi_assert_count[cnt])
-#define hvm_isa_irq_to_gsi(isa_irq) ((isa_irq) ? : 2)
+unsigned int hvm_isa_irq_to_gsi(const struct domain *d, unsigned int irq);
/* Check/Acknowledge next pending interrupt. */
struct hvm_intack hvm_vcpu_has_pending_irq(struct vcpu *v);
@@ -205,4 +205,7 @@ unsigned highest_gsi(void);
int ioapic_guest_read( unsigned long physbase, unsigned int reg, u32 *pval);
int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 pval);
+int io_apic_find_isa_irq_pin(int irq, int type);
+int io_apic_find_isa_irq_apic(int irq, int type);
+
#endif
The current function has the ISA IRQ 0 hardcoded to GSI 2 for HVM domUs. Allow such function to also be used by the hardware domain by taking into account the ACPI interrupt overwrites in order to get the correct ISA to GSI mappings. This requires passing a domain parameter to the helper, since it's not guaranteed to always be called with current being the destination vCPU. No functional change intended. Signed-off-by: Roger Pau Monné <roger.pau@citrix.com> --- xen/arch/x86/hvm/irq.c | 20 +++++++++++++++++--- xen/arch/x86/hvm/vioapic.c | 2 +- xen/arch/x86/hvm/vpic.c | 7 +++++-- xen/arch/x86/hvm/vpt.c | 5 +++-- xen/arch/x86/io_apic.c | 16 ++++++++-------- xen/include/asm-x86/hvm/irq.h | 2 +- xen/include/asm-x86/io_apic.h | 3 +++ 7 files changed, 38 insertions(+), 17 deletions(-)