extern int smp_num_siblings;
 extern cpumask_t cpu_sibling_map[];
 extern cpumask_t cpu_core_map[];
-extern cpumask_t cpu_foreign_map;
+extern cpumask_t cpu_foreign_map[];
 
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
 
  * A logcal cpu mask containing only one VPE per core to
  * reduce the number of IPIs on large MT systems.
  */
-cpumask_t cpu_foreign_map __read_mostly;
+cpumask_t cpu_foreign_map[NR_CPUS] __read_mostly;
 EXPORT_SYMBOL(cpu_foreign_map);
 
 /* representing cpus for which sibling maps can be computed */
                        cpumask_set_cpu(i, &temp_foreign_map);
        }
 
-       cpumask_copy(&cpu_foreign_map, &temp_foreign_map);
+       for_each_online_cpu(i)
+               cpumask_andnot(&cpu_foreign_map[i],
+                              &temp_foreign_map, &cpu_sibling_map[i]);
 }
 
 struct plat_smp_ops *mp_ops;
 
  * @type:      Type of cache operations (R4K_HIT or R4K_INDEX).
  *
  * Decides whether a cache op needs to be performed on every core in the system.
- * This may change depending on the @type of cache operation.
+ * This may change depending on the @type of cache operation, as well as the set
+ * of online CPUs, so preemption should be disabled by the caller to prevent CPU
+ * hotplug from changing the result.
  *
  * Returns:    1 if the cache operation @type should be done on every core in
  *             the system.
 
        /*
         * Hardware doesn't globalize the required cache ops, so SMP calls may
-        * be needed.
+        * be needed, but only if there are foreign CPUs (non-siblings with
+        * separate caches).
         */
-       return true;
+       /* cpu_foreign_map[] undeclared when !CONFIG_SMP */
+#ifdef CONFIG_SMP
+       return !cpumask_empty(&cpu_foreign_map[0]);
+#else
+       return false;
+#endif
 }
 
 /*
 {
        preempt_disable();
        if (r4k_op_needs_ipi(type))
-               smp_call_function_many(&cpu_foreign_map, func, info, 1);
+               smp_call_function_many(&cpu_foreign_map[smp_processor_id()],
+                                      func, info, 1);
        func(info);
        preempt_enable();
 }