Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/x86/kernel/apic/ipi.c
17372 views
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
#ifdef CONFIG_X86_32
60
61
void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
62
int vector)
63
{
64
unsigned long flags;
65
unsigned int query_cpu;
66
67
/*
68
* Hack. The clustered APIC addressing mode doesn't allow us to send
69
* to an arbitrary mask, so I do a unicasts to each CPU instead. This
70
* should be modified to do 1 message per cluster ID - mbligh
71
*/
72
73
local_irq_save(flags);
74
for_each_cpu(query_cpu, mask)
75
__default_send_IPI_dest_field(
76
early_per_cpu(x86_cpu_to_logical_apicid, query_cpu),
77
vector, apic->dest_logical);
78
local_irq_restore(flags);
79
}
80
81
void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask,
82
int vector)
83
{
84
unsigned long flags;
85
unsigned int query_cpu;
86
unsigned int this_cpu = smp_processor_id();
87
88
/* See Hack comment above */
89
90
local_irq_save(flags);
91
for_each_cpu(query_cpu, mask) {
92
if (query_cpu == this_cpu)
93
continue;
94
__default_send_IPI_dest_field(
95
early_per_cpu(x86_cpu_to_logical_apicid, query_cpu),
96
vector, apic->dest_logical);
97
}
98
local_irq_restore(flags);
99
}
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
169