|
@@ -44,6 +44,8 @@ static u64 gru_start_paddr, gru_end_paddr;
|
|
|
static union uvh_apicid uvh_apicid;
|
|
|
int uv_min_hub_revision_id;
|
|
|
EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
|
|
|
+unsigned int uv_apicid_hibits;
|
|
|
+EXPORT_SYMBOL_GPL(uv_apicid_hibits);
|
|
|
static DEFINE_SPINLOCK(uv_nmi_lock);
|
|
|
|
|
|
static inline bool is_GRU_range(u64 start, u64 end)
|
|
@@ -85,6 +87,23 @@ static void __init early_get_apic_pnode_shift(void)
|
|
|
uvh_apicid.s.pnode_shift = UV_APIC_PNODE_SHIFT;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Add an extra bit as dictated by bios to the destination apicid of
|
|
|
+ * interrupts potentially passing through the UV HUB. This prevents
|
|
|
+ * a deadlock between interrupts and IO port operations.
|
|
|
+ */
|
|
|
+static void __init uv_set_apicid_hibit(void)
|
|
|
+{
|
|
|
+ union uvh_lb_target_physical_apic_id_mask_u apicid_mask;
|
|
|
+ unsigned long *mmr;
|
|
|
+
|
|
|
+ mmr = early_ioremap(UV_LOCAL_MMR_BASE |
|
|
|
+ UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK, sizeof(*mmr));
|
|
|
+ apicid_mask.v = *mmr;
|
|
|
+ early_iounmap(mmr, sizeof(*mmr));
|
|
|
+ uv_apicid_hibits = apicid_mask.s.bit_enables & UV_APICID_HIBIT_MASK;
|
|
|
+}
|
|
|
+
|
|
|
static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
|
|
{
|
|
|
int nodeid;
|
|
@@ -102,6 +121,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
|
|
__get_cpu_var(x2apic_extra_bits) =
|
|
|
nodeid << (uvh_apicid.s.pnode_shift - 1);
|
|
|
uv_system_type = UV_NON_UNIQUE_APIC;
|
|
|
+ uv_set_apicid_hibit();
|
|
|
return 1;
|
|
|
}
|
|
|
}
|
|
@@ -155,6 +175,7 @@ static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_ri
|
|
|
int pnode;
|
|
|
|
|
|
pnode = uv_apicid_to_pnode(phys_apicid);
|
|
|
+ phys_apicid |= uv_apicid_hibits;
|
|
|
val = (1UL << UVH_IPI_INT_SEND_SHFT) |
|
|
|
(phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
|
|
|
((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
|
|
@@ -236,7 +257,7 @@ static unsigned int uv_cpu_mask_to_apicid(const struct cpumask *cpumask)
|
|
|
int cpu = cpumask_first(cpumask);
|
|
|
|
|
|
if ((unsigned)cpu < nr_cpu_ids)
|
|
|
- return per_cpu(x86_cpu_to_apicid, cpu);
|
|
|
+ return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
|
|
|
else
|
|
|
return BAD_APICID;
|
|
|
}
|
|
@@ -255,7 +276,7 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
|
|
|
if (cpumask_test_cpu(cpu, cpu_online_mask))
|
|
|
break;
|
|
|
}
|
|
|
- return per_cpu(x86_cpu_to_apicid, cpu);
|
|
|
+ return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
|
|
|
}
|
|
|
|
|
|
static unsigned int x2apic_get_apic_id(unsigned long x)
|