1 #include <linux/cpumask.h> 2 #include <linux/interrupt.h> 3 #include <linux/init.h> 4 5 #include <linux/mm.h> 6 #include <linux/delay.h> 7 #include <linux/spinlock.h> 8 #include <linux/kernel_stat.h> 9 #include <linux/mc146818rtc.h> 10 #include <linux/cache.h> 11 #include <linux/cpu.h> 12 #include <linux/module.h> 13 14 #include <asm/smp.h> 15 #include <asm/mtrr.h> 16 #include <asm/tlbflush.h> 17 #include <asm/mmu_context.h> 18 #include <asm/apic.h> 19 #include <asm/proto.h> 20 #include <asm/ipi.h> 21 22 void default_send_IPI_mask_sequence_phys(const struct cpumask *mask, int vector) 23 { 24 unsigned long query_cpu; 25 unsigned long flags; 26 27 /* 28 * Hack. The clustered APIC addressing mode doesn't allow us to send 29 * to an arbitrary mask, so I do a unicast to each CPU instead. 30 * - mbligh 31 */ 32 local_irq_save(flags); 33 for_each_cpu(query_cpu, mask) { 34 __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, 35 query_cpu), vector, APIC_DEST_PHYSICAL); 36 } 37 local_irq_restore(flags); 38 } 39 40 void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask, 41 int vector) 42 { 43 unsigned int this_cpu = smp_processor_id(); 44 unsigned int query_cpu; 45 unsigned long flags; 46 47 /* See Hack comment above */ 48 49 local_irq_save(flags); 50 for_each_cpu(query_cpu, mask) { 51 if (query_cpu == this_cpu) 52 continue; 53 __default_send_IPI_dest_field(per_cpu(x86_cpu_to_apicid, 54 query_cpu), vector, APIC_DEST_PHYSICAL); 55 } 56 local_irq_restore(flags); 57 } 58 59 void default_send_IPI_mask_sequence_logical(const struct cpumask *mask, 60 int vector) 61 { 62 unsigned long flags; 63 unsigned int query_cpu; 64 65 /* 66 * Hack. The clustered APIC addressing mode doesn't allow us to send 67 * to an arbitrary mask, so I do a unicasts to each CPU instead. This 68 * should be modified to do 1 message per cluster ID - mbligh 69 */ 70 71 local_irq_save(flags); 72 for_each_cpu(query_cpu, mask) 73 __default_send_IPI_dest_field( 74 apic->cpu_to_logical_apicid(query_cpu), vector, 75 apic->dest_logical); 76 local_irq_restore(flags); 77 } 78 79 void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask, 80 int vector) 81 { 82 unsigned long flags; 83 unsigned int query_cpu; 84 unsigned int this_cpu = smp_processor_id(); 85 86 /* See Hack comment above */ 87 88 local_irq_save(flags); 89 for_each_cpu(query_cpu, mask) { 90 if (query_cpu == this_cpu) 91 continue; 92 __default_send_IPI_dest_field( 93 apic->cpu_to_logical_apicid(query_cpu), vector, 94 apic->dest_logical); 95 } 96 local_irq_restore(flags); 97 } 98 99 #ifdef CONFIG_X86_32 100 101 /* 102 * This is only used on smaller machines. 103 */ 104 void default_send_IPI_mask_logical(const struct cpumask *cpumask, int vector) 105 { 106 unsigned long mask = cpumask_bits(cpumask)[0]; 107 unsigned long flags; 108 109 if (WARN_ONCE(!mask, "empty IPI mask")) 110 return; 111 112 local_irq_save(flags); 113 WARN_ON(mask & ~cpumask_bits(cpu_online_mask)[0]); 114 __default_send_IPI_dest_field(mask, vector, apic->dest_logical); 115 local_irq_restore(flags); 116 } 117 118 void default_send_IPI_allbutself(int vector) 119 { 120 /* 121 * if there are no other CPUs in the system then we get an APIC send 122 * error if we try to broadcast, thus avoid sending IPIs in this case. 123 */ 124 if (!(num_online_cpus() > 1)) 125 return; 126 127 __default_local_send_IPI_allbutself(vector); 128 } 129 130 void default_send_IPI_all(int vector) 131 { 132 __default_local_send_IPI_all(vector); 133 } 134 135 void default_send_IPI_self(int vector) 136 { 137 __default_send_IPI_shortcut(APIC_DEST_SELF, vector, apic->dest_logical); 138 } 139 140 /* must come after the send_IPI functions above for inlining */ 141 static int convert_apicid_to_cpu(int apic_id) 142 { 143 int i; 144 145 for_each_possible_cpu(i) { 146 if (per_cpu(x86_cpu_to_apicid, i) == apic_id) 147 return i; 148 } 149 return -1; 150 } 151 152 int safe_smp_processor_id(void) 153 { 154 int apicid, cpuid; 155 156 if (!cpu_has_apic) 157 return 0; 158 159 apicid = hard_smp_processor_id(); 160 if (apicid == BAD_APICID) 161 return 0; 162 163 cpuid = convert_apicid_to_cpu(apicid); 164 165 return cpuid >= 0 ? cpuid : 0; 166 } 167 #endif 168