aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorCyrill Gorcunov <gorcunov@openvz.org>2009-10-13 16:07:03 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-14 03:17:00 -0400
commit9844ab11c763bfed9f054c82366b19dcda66aca9 (patch)
tree750c241236a5bf1b743f3bffae7ffff47ff14ca9 /arch
parent80f506918fdaaca6b574ba931536a58ce015c7be (diff)
x86, apic: Introduce the NOOP apic driver
Introduce NOOP APIC driver. We should use it in case if apic was disabled due to hardware of software/firmware problems (including user requested to disable it case). The driver is attempting to catch any inappropriate apic operation call with warning issue. Also it is possible to use some apic operation like IPI calls, read/write without checking for apic presence which should make callers code easier. Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Cc: yinghai@kernel.org Cc: macro@linux-mips.org LKML-Reference: <20091013201022.534682104@openvz.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/apic.h2
-rw-r--r--arch/x86/kernel/apic/Makefile2
-rw-r--r--arch/x86/kernel/apic/apic_noop.c194
3 files changed, 197 insertions, 1 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 474d80d3e6cc..08a5f420e07b 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -488,6 +488,8 @@ static inline unsigned int read_apic_id(void)
488 488
489extern void default_setup_apic_routing(void); 489extern void default_setup_apic_routing(void);
490 490
491extern struct apic apic_noop;
492
491#ifdef CONFIG_X86_32 493#ifdef CONFIG_X86_32
492 494
493extern struct apic apic_default; 495extern struct apic apic_default;
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile
index da7b7b9f8bd8..565c1bfc507d 100644
--- a/arch/x86/kernel/apic/Makefile
+++ b/arch/x86/kernel/apic/Makefile
@@ -2,7 +2,7 @@
2# Makefile for local APIC drivers and for the IO-APIC code 2# Makefile for local APIC drivers and for the IO-APIC code
3# 3#
4 4
5obj-$(CONFIG_X86_LOCAL_APIC) += apic.o probe_$(BITS).o ipi.o nmi.o 5obj-$(CONFIG_X86_LOCAL_APIC) += apic.o apic_noop.o probe_$(BITS).o ipi.o nmi.o
6obj-$(CONFIG_X86_IO_APIC) += io_apic.o 6obj-$(CONFIG_X86_IO_APIC) += io_apic.o
7obj-$(CONFIG_SMP) += ipi.o 7obj-$(CONFIG_SMP) += ipi.o
8 8
diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c
new file mode 100644
index 000000000000..0b93ec2fde0a
--- /dev/null
+++ b/arch/x86/kernel/apic/apic_noop.c
@@ -0,0 +1,194 @@
1/*
2 * NOOP APIC driver.
3 *
4 * Does almost nothing and should be substituted by a real apic driver via
5 * probe routine.
6 *
7 * Though in case if apic is disabled (for some reason) we try
8 * to not uglify the caller's code and allow to call (some) apic routines
9 * like self-ipi, etc... and issue a warning if an operation is not allowed
10 */
11
12#include <linux/threads.h>
13#include <linux/cpumask.h>
14#include <linux/module.h>
15#include <linux/string.h>
16#include <linux/kernel.h>
17#include <linux/ctype.h>
18#include <linux/init.h>
19#include <linux/errno.h>
20#include <asm/fixmap.h>
21#include <asm/mpspec.h>
22#include <asm/apicdef.h>
23#include <asm/apic.h>
24#include <asm/setup.h>
25
26#include <linux/smp.h>
27#include <asm/ipi.h>
28
29#include <linux/interrupt.h>
30#include <asm/acpi.h>
31#include <asm/e820.h>
32
33/*
34 * some operations should never be reached with
35 * noop apic if it's not turned off, this mostly
36 * means the caller forgot to disable apic (or
37 * check the apic presence) before doing a call
38 */
39static void warn_apic_enabled(void)
40{
41 WARN_ONCE((cpu_has_apic || !disable_apic),
42 "APIC: Called for NOOP operation with apic enabled\n");
43}
44
45/*
46 * To check operations but do not bloat source code
47 */
48#define NOOP_FUNC(func) func { warn_apic_enabled(); }
49#define NOOP_FUNC_RET(func, ret) func { warn_apic_enabled(); return ret; }
50
51NOOP_FUNC(static void noop_init_apic_ldr(void))
52NOOP_FUNC(static void noop_send_IPI_mask(const struct cpumask *cpumask, int vector))
53NOOP_FUNC(static void noop_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector))
54NOOP_FUNC(static void noop_send_IPI_allbutself(int vector))
55NOOP_FUNC(static void noop_send_IPI_all(int vector))
56NOOP_FUNC(static void noop_send_IPI_self(int vector))
57NOOP_FUNC_RET(static int noop_wakeup_secondary_cpu(int apicid, unsigned long start_eip), -1)
58NOOP_FUNC(static void noop_apic_write(u32 reg, u32 v))
59NOOP_FUNC(void noop_apic_wait_icr_idle(void))
60NOOP_FUNC_RET(static u32 noop_safe_apic_wait_icr_idle(void), 0)
61NOOP_FUNC_RET(static u64 noop_apic_icr_read(void), 0)
62NOOP_FUNC(static void noop_apic_icr_write(u32 low, u32 id))
63NOOP_FUNC_RET(static physid_mask_t noop_ioapic_phys_id_map(physid_mask_t phys_map), phys_map)
64NOOP_FUNC_RET(static int noop_cpu_to_logical_apicid(int cpu), 1)
65NOOP_FUNC_RET(static int noop_default_phys_pkg_id(int cpuid_apic, int index_msb), 0)
66NOOP_FUNC_RET(static unsigned int noop_get_apic_id(unsigned long x), 0)
67
68static int noop_probe(void)
69{
70 /* should not ever be enabled this way */
71 return 0;
72}
73
74static int noop_apic_id_registered(void)
75{
76 warn_apic_enabled();
77 return physid_isset(read_apic_id(), phys_cpu_present_map);
78}
79
80static const struct cpumask *noop_target_cpus(void)
81{
82 warn_apic_enabled();
83
84 /* only BSP here */
85 return cpumask_of(0);
86}
87
88static unsigned long noop_check_apicid_used(physid_mask_t bitmap, int apicid)
89{
90 warn_apic_enabled();
91 return physid_isset(apicid, bitmap);
92}
93
94static unsigned long noop_check_apicid_present(int bit)
95{
96 warn_apic_enabled();
97 return physid_isset(bit, phys_cpu_present_map);
98}
99
100static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask)
101{
102 warn_apic_enabled();
103 if (cpu != 0)
104 pr_warning("APIC: Vector allocated for non-BSP cpu\n");
105 cpumask_clear(retmask);
106 cpumask_set_cpu(cpu, retmask);
107}
108
109int noop_apicid_to_node(int logical_apicid)
110{
111 warn_apic_enabled();
112
113 /* we're always on node 0 */
114 return 0;
115}
116
117static u32 noop_apic_read(u32 reg)
118{
119 /*
120 * noop-read is always safe until we have
121 * non-disabled unit
122 */
123 WARN_ON_ONCE((cpu_has_apic && !disable_apic));
124 return 0;
125}
126
127struct apic apic_noop = {
128 .name = "noop",
129 .probe = noop_probe,
130 .acpi_madt_oem_check = NULL,
131
132 .apic_id_registered = noop_apic_id_registered,
133
134 .irq_delivery_mode = dest_LowestPrio,
135 /* logical delivery broadcast to all CPUs: */
136 .irq_dest_mode = 1,
137
138 .target_cpus = noop_target_cpus,
139 .disable_esr = 0,
140 .dest_logical = APIC_DEST_LOGICAL,
141 .check_apicid_used = noop_check_apicid_used,
142 .check_apicid_present = noop_check_apicid_present,
143
144 .vector_allocation_domain = noop_vector_allocation_domain,
145 .init_apic_ldr = noop_init_apic_ldr,
146
147 .ioapic_phys_id_map = noop_ioapic_phys_id_map,
148 .setup_apic_routing = NULL,
149 .multi_timer_check = NULL,
150 .apicid_to_node = noop_apicid_to_node,
151
152 .cpu_to_logical_apicid = noop_cpu_to_logical_apicid,
153 .cpu_present_to_apicid = default_cpu_present_to_apicid,
154 .apicid_to_cpu_present = default_apicid_to_cpu_present,
155
156 .setup_portio_remap = NULL,
157 .check_phys_apicid_present = default_check_phys_apicid_present,
158 .enable_apic_mode = NULL,
159
160 .phys_pkg_id = noop_default_phys_pkg_id,
161
162 .mps_oem_check = NULL,
163
164 .get_apic_id = noop_get_apic_id,
165 .set_apic_id = NULL,
166 .apic_id_mask = 0x0F << 24,
167
168 .cpu_mask_to_apicid = default_cpu_mask_to_apicid,
169 .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and,
170
171 .send_IPI_mask = noop_send_IPI_mask,
172 .send_IPI_mask_allbutself = noop_send_IPI_mask_allbutself,
173 .send_IPI_allbutself = noop_send_IPI_allbutself,
174 .send_IPI_all = noop_send_IPI_all,
175 .send_IPI_self = noop_send_IPI_self,
176
177 .wakeup_secondary_cpu = noop_wakeup_secondary_cpu,
178
179 /* should be safe */
180 .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
181 .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
182
183 .wait_for_init_deassert = NULL,
184
185 .smp_callin_clear_local_apic = NULL,
186 .inquire_remote_apic = NULL,
187
188 .read = noop_apic_read,
189 .write = noop_apic_write,
190 .icr_read = noop_apic_icr_read,
191 .icr_write = noop_apic_icr_write,
192 .wait_icr_idle = noop_apic_wait_icr_idle,
193 .safe_wait_icr_idle = noop_safe_apic_wait_icr_idle,
194};