]> rtime.felk.cvut.cz Git - jailhouse.git/commitdiff
apic: extract irq validation logic from iommu_map_interrupt
authorHenning Schild <henning.schild@siemens.com>
Mon, 24 Nov 2014 17:54:05 +0000 (18:54 +0100)
committerJan Kiszka <jan.kiszka@siemens.com>
Tue, 25 Nov 2014 12:26:01 +0000 (13:26 +0100)
Introducing a new function apic_irq_dest_in_cell that makes sure the
destination cpu of the interrupt belongs to the given cell.
So far this code was part of iommu_map_interrupt but these checks are
required in other places as well.

Signed-off-by: Henning Schild <henning.schild@siemens.com>
[Jan: trivial formatting adjustments]
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
hypervisor/arch/x86/apic.c
hypervisor/arch/x86/include/asm/apic.h
hypervisor/arch/x86/vtd.c

index cb2c9994f6312967249fc78d7bd267291bc8eb1d..76df576da8f75ec8dd3e3dea09f922f50c103f83 100644 (file)
@@ -206,6 +206,42 @@ void apic_send_nmi_ipi(struct per_cpu *target_data)
                          APIC_ICR_SH_NONE);
 }
 
+/**
+ * Return whether an interrupt's destination CPU is within a given cell. Also
+ * return a filtered destination mask.
+ *
+ * @param cell         Target cell
+ * @param irq_msg      Pointer to the irq message to be checked
+ *                     The data structure might get adjusted by calling this
+ *                     function.
+ *
+ * @see x2apic_filter_logical_dest
+ *
+ * @return "true" if the interrupt is for the given cell, "false" if not.
+ */
+bool apic_filter_irq_dest(struct cell *cell, struct apic_irq_message *irq_msg)
+{
+       u32 dest = irq_msg->destination;
+
+       if (irq_msg->dest_logical) {
+               if (using_x2apic)
+                       dest = x2apic_filter_logical_dest(cell, dest);
+               else
+                       dest &= cell->cpu_set->bitmap[0];
+               /*
+                * Linux may have programmed inactive vectors with too broad
+                * destination masks. Return the adjusted mask and do not fail.
+                */
+               if (dest != irq_msg->destination && cell != &root_cell)
+                       return false;
+               irq_msg->destination = dest;
+       } else if (dest > APIC_MAX_PHYS_ID ||
+                  !cell_owns_cpu(cell, apic_to_cpu_id[dest])) {
+               return false;
+       }
+       return true;
+}
+
 void apic_send_irq(struct apic_irq_message irq_msg)
 {
        u32 delivery_mode = irq_msg.delivery_mode << APIC_ICR_DLVR_SHIFT;
index c80f27fe5f2f0b1ad64500120605b2ebe3a60c81..6f36de678398ff546c0f8d7a1fe9c8d1d3fbb3df 100644 (file)
@@ -156,6 +156,7 @@ int apic_cpu_init(struct per_cpu *cpu_data);
 void apic_clear(struct per_cpu *cpu_data);
 
 void apic_send_nmi_ipi(struct per_cpu *target_data);
+bool apic_filter_irq_dest(struct cell *cell, struct apic_irq_message *irq_msg);
 void apic_send_irq(struct apic_irq_message irq_msg);
 
 void apic_irq_handler(void);
index e79ed52b8c59fb19bcff4ad05b4e6d85b1148fb6..a1c2330751bcaebec9808b0e5ebba25658c04772 100644 (file)
@@ -825,7 +825,6 @@ iommu_get_remapped_root_int(unsigned int iommu, u16 device_id,
 int iommu_map_interrupt(struct cell *cell, u16 device_id, unsigned int vector,
                        struct apic_irq_message irq_msg)
 {
-       u32 dest = irq_msg.destination;
        union vtd_irte irte;
        int base_index;
 
@@ -862,29 +861,15 @@ int iommu_map_interrupt(struct cell *cell, u16 device_id, unsigned int vector,
             irq_msg.delivery_mode != APIC_MSG_DLVR_LOWPRI) ||
            irq_msg.dest_logical != irq_msg.redir_hint)
                return -EINVAL;
-       if (irq_msg.dest_logical) {
-               if (using_x2apic)
-                       dest = x2apic_filter_logical_dest(cell, dest);
-               else
-                       dest &= cell->cpu_set->bitmap[0];
-               /*
-                * Linux may have programmed inactive vectors with too broad
-                * destination masks. Silently adjust them when programming the
-                * IRTE instead of failing the whole cell here.
-                */
-               if (dest != irq_msg.destination && cell != &root_cell)
-                       return -EPERM;
-       } else if (dest > APIC_MAX_PHYS_ID ||
-                  !cell_owns_cpu(cell, apic_to_cpu_id[dest])) {
+       if (!apic_filter_irq_dest(cell, &irq_msg))
                return -EPERM;
-       }
 
        irte.field.dest_logical = irq_msg.dest_logical;
        irte.field.redir_hint = irq_msg.redir_hint;
        irte.field.level_triggered = irq_msg.level_triggered;
        irte.field.delivery_mode = irq_msg.delivery_mode;
        irte.field.vector = irq_msg.vector;
-       irte.field.destination = dest;
+       irte.field.destination = irq_msg.destination;
        if (!using_x2apic)
                /* xAPIC in flat mode: APIC ID in 47:40 (of 63:32) */
                irte.field.destination <<= 8;