diff options
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/apic/ipi.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/arch/x86/kernel/apic/ipi.c b/arch/x86/kernel/apic/ipi.c index eb45fc9b6124..28bde88b0085 100644 --- a/arch/x86/kernel/apic/ipi.c +++ b/arch/x86/kernel/apic/ipi.c | |||
@@ -18,6 +18,66 @@ | |||
18 | #include <asm/proto.h> | 18 | #include <asm/proto.h> |
19 | #include <asm/ipi.h> | 19 | #include <asm/ipi.h> |
20 | 20 | ||
21 | void __default_send_IPI_shortcut(unsigned int shortcut, int vector, unsigned int dest) | ||
22 | { | ||
23 | /* | ||
24 | * Subtle. In the case of the 'never do double writes' workaround | ||
25 | * we have to lock out interrupts to be safe. As we don't care | ||
26 | * of the value read we use an atomic rmw access to avoid costly | ||
27 | * cli/sti. Otherwise we use an even cheaper single atomic write | ||
28 | * to the APIC. | ||
29 | */ | ||
30 | unsigned int cfg; | ||
31 | |||
32 | /* | ||
33 | * Wait for idle. | ||
34 | */ | ||
35 | __xapic_wait_icr_idle(); | ||
36 | |||
37 | /* | ||
38 | * No need to touch the target chip field | ||
39 | */ | ||
40 | cfg = __prepare_ICR(shortcut, vector, dest); | ||
41 | |||
42 | /* | ||
43 | * Send the IPI. The write to APIC_ICR fires this off. | ||
44 | */ | ||
45 | native_apic_mem_write(APIC_ICR, cfg); | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * This is used to send an IPI with no shorthand notation (the destination is | ||
50 | * specified in bits 56 to 63 of the ICR). | ||
51 | */ | ||
52 | void __default_send_IPI_dest_field(unsigned int mask, int vector, unsigned int dest) | ||
53 | { | ||
54 | unsigned long cfg; | ||
55 | |||
56 | /* | ||
57 | * Wait for idle. | ||
58 | */ | ||
59 | if (unlikely(vector == NMI_VECTOR)) | ||
60 | safe_apic_wait_icr_idle(); | ||
61 | else | ||
62 | __xapic_wait_icr_idle(); | ||
63 | |||
64 | /* | ||
65 | * prepare target chip field | ||
66 | */ | ||
67 | cfg = __prepare_ICR2(mask); | ||
68 | native_apic_mem_write(APIC_ICR2, cfg); | ||
69 | |||
70 | /* | ||
71 | * program the ICR | ||
72 | */ | ||
73 | cfg = __prepare_ICR(0, vector, dest); | ||
74 | |||
75 | /* | ||
76 | * Send the IPI. The write to APIC_ICR fires this off. | ||
77 | */ | ||
78 | native_apic_mem_write(APIC_ICR, cfg); | ||
79 | } | ||
80 | |||
21 | void default_send_IPI_single_phys(int cpu, int vector) | 81 | void default_send_IPI_single_phys(int cpu, int vector) |
22 | { | 82 | { |
23 | unsigned long flags; | 83 | unsigned long flags; |