Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 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 |
Cyrill Gorcunov | f88f2b4 | 2009-10-15 19:04:16 +0400 | [diff] [blame] | 9 | * like self-ipi, etc... |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 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 | |
Cyrill Gorcunov | f88f2b4 | 2009-10-15 19:04:16 +0400 | [diff] [blame] | 33 | static void noop_init_apic_ldr(void) { } |
| 34 | static void noop_send_IPI_mask(const struct cpumask *cpumask, int vector) { } |
| 35 | static void noop_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector) { } |
| 36 | static void noop_send_IPI_allbutself(int vector) { } |
| 37 | static void noop_send_IPI_all(int vector) { } |
| 38 | static void noop_send_IPI_self(int vector) { } |
| 39 | static void noop_apic_wait_icr_idle(void) { } |
| 40 | static void noop_apic_icr_write(u32 low, u32 id) { } |
| 41 | |
| 42 | static int noop_wakeup_secondary_cpu(int apicid, unsigned long start_eip) |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 43 | { |
Cyrill Gorcunov | f88f2b4 | 2009-10-15 19:04:16 +0400 | [diff] [blame] | 44 | return -1; |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 45 | } |
| 46 | |
Cyrill Gorcunov | f88f2b4 | 2009-10-15 19:04:16 +0400 | [diff] [blame] | 47 | static u32 noop_safe_apic_wait_icr_idle(void) |
| 48 | { |
| 49 | return 0; |
| 50 | } |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 51 | |
Cyrill Gorcunov | f88f2b4 | 2009-10-15 19:04:16 +0400 | [diff] [blame] | 52 | static u64 noop_apic_icr_read(void) |
| 53 | { |
| 54 | return 0; |
| 55 | } |
| 56 | |
Cyrill Gorcunov | f88f2b4 | 2009-10-15 19:04:16 +0400 | [diff] [blame] | 57 | static int noop_phys_pkg_id(int cpuid_apic, int index_msb) |
| 58 | { |
| 59 | return 0; |
| 60 | } |
| 61 | |
| 62 | static unsigned int noop_get_apic_id(unsigned long x) |
| 63 | { |
| 64 | return 0; |
| 65 | } |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 66 | |
| 67 | static int noop_probe(void) |
| 68 | { |
Cyrill Gorcunov | f88f2b4 | 2009-10-15 19:04:16 +0400 | [diff] [blame] | 69 | /* |
| 70 | * NOOP apic should not ever be |
| 71 | * enabled via probe routine |
| 72 | */ |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 73 | return 0; |
| 74 | } |
| 75 | |
| 76 | static int noop_apic_id_registered(void) |
| 77 | { |
Cyrill Gorcunov | f88f2b4 | 2009-10-15 19:04:16 +0400 | [diff] [blame] | 78 | /* |
| 79 | * if we would be really "pedantic" |
| 80 | * we should pass read_apic_id() here |
| 81 | * but since NOOP suppose APIC ID = 0 |
| 82 | * lets save a few cycles |
| 83 | */ |
| 84 | return physid_isset(0, phys_cpu_present_map); |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | static const struct cpumask *noop_target_cpus(void) |
| 88 | { |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 89 | /* only BSP here */ |
| 90 | return cpumask_of(0); |
| 91 | } |
| 92 | |
Cyrill Gorcunov | 7abc075 | 2009-11-10 01:06:59 +0300 | [diff] [blame] | 93 | static unsigned long noop_check_apicid_used(physid_mask_t *map, int apicid) |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 94 | { |
Cyrill Gorcunov | 7abc075 | 2009-11-10 01:06:59 +0300 | [diff] [blame] | 95 | return physid_isset(apicid, *map); |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | static unsigned long noop_check_apicid_present(int bit) |
| 99 | { |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 100 | return physid_isset(bit, phys_cpu_present_map); |
| 101 | } |
| 102 | |
| 103 | static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask) |
| 104 | { |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 105 | if (cpu != 0) |
| 106 | pr_warning("APIC: Vector allocated for non-BSP cpu\n"); |
| 107 | cpumask_clear(retmask); |
| 108 | cpumask_set_cpu(cpu, retmask); |
| 109 | } |
| 110 | |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 111 | static u32 noop_apic_read(u32 reg) |
| 112 | { |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 113 | WARN_ON_ONCE((cpu_has_apic && !disable_apic)); |
| 114 | return 0; |
| 115 | } |
| 116 | |
Cyrill Gorcunov | f88f2b4 | 2009-10-15 19:04:16 +0400 | [diff] [blame] | 117 | static void noop_apic_write(u32 reg, u32 v) |
| 118 | { |
Thomas Gleixner | a946d8f1 | 2009-12-07 12:59:46 +0100 | [diff] [blame] | 119 | WARN_ON_ONCE(cpu_has_apic && !disable_apic); |
Cyrill Gorcunov | f88f2b4 | 2009-10-15 19:04:16 +0400 | [diff] [blame] | 120 | } |
| 121 | |
Tejun Heo | 89e5dc2 | 2011-01-23 14:37:38 +0100 | [diff] [blame] | 122 | #ifdef CONFIG_X86_32 |
| 123 | static int noop_x86_32_numa_cpu_node(int cpu) |
| 124 | { |
| 125 | /* we're always on node 0 */ |
| 126 | return 0; |
| 127 | } |
| 128 | #endif |
| 129 | |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 130 | struct apic apic_noop = { |
| 131 | .name = "noop", |
| 132 | .probe = noop_probe, |
| 133 | .acpi_madt_oem_check = NULL, |
| 134 | |
| 135 | .apic_id_registered = noop_apic_id_registered, |
| 136 | |
| 137 | .irq_delivery_mode = dest_LowestPrio, |
| 138 | /* logical delivery broadcast to all CPUs: */ |
| 139 | .irq_dest_mode = 1, |
| 140 | |
| 141 | .target_cpus = noop_target_cpus, |
| 142 | .disable_esr = 0, |
| 143 | .dest_logical = APIC_DEST_LOGICAL, |
| 144 | .check_apicid_used = noop_check_apicid_used, |
| 145 | .check_apicid_present = noop_check_apicid_present, |
| 146 | |
| 147 | .vector_allocation_domain = noop_vector_allocation_domain, |
| 148 | .init_apic_ldr = noop_init_apic_ldr, |
| 149 | |
Cyrill Gorcunov | 7abc075 | 2009-11-10 01:06:59 +0300 | [diff] [blame] | 150 | .ioapic_phys_id_map = default_ioapic_phys_id_map, |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 151 | .setup_apic_routing = NULL, |
| 152 | .multi_timer_check = NULL, |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 153 | |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 154 | .cpu_present_to_apicid = default_cpu_present_to_apicid, |
Cyrill Gorcunov | 7abc075 | 2009-11-10 01:06:59 +0300 | [diff] [blame] | 155 | .apicid_to_cpu_present = physid_set_mask_of_physid, |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 156 | |
| 157 | .setup_portio_remap = NULL, |
| 158 | .check_phys_apicid_present = default_check_phys_apicid_present, |
| 159 | .enable_apic_mode = NULL, |
| 160 | |
Cyrill Gorcunov | f88f2b4 | 2009-10-15 19:04:16 +0400 | [diff] [blame] | 161 | .phys_pkg_id = noop_phys_pkg_id, |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 162 | |
| 163 | .mps_oem_check = NULL, |
| 164 | |
| 165 | .get_apic_id = noop_get_apic_id, |
| 166 | .set_apic_id = NULL, |
| 167 | .apic_id_mask = 0x0F << 24, |
| 168 | |
| 169 | .cpu_mask_to_apicid = default_cpu_mask_to_apicid, |
| 170 | .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, |
| 171 | |
| 172 | .send_IPI_mask = noop_send_IPI_mask, |
| 173 | .send_IPI_mask_allbutself = noop_send_IPI_mask_allbutself, |
| 174 | .send_IPI_allbutself = noop_send_IPI_allbutself, |
| 175 | .send_IPI_all = noop_send_IPI_all, |
| 176 | .send_IPI_self = noop_send_IPI_self, |
| 177 | |
| 178 | .wakeup_secondary_cpu = noop_wakeup_secondary_cpu, |
| 179 | |
| 180 | /* should be safe */ |
| 181 | .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, |
| 182 | .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, |
| 183 | |
| 184 | .wait_for_init_deassert = NULL, |
| 185 | |
| 186 | .smp_callin_clear_local_apic = NULL, |
| 187 | .inquire_remote_apic = NULL, |
| 188 | |
| 189 | .read = noop_apic_read, |
| 190 | .write = noop_apic_write, |
| 191 | .icr_read = noop_apic_icr_read, |
| 192 | .icr_write = noop_apic_icr_write, |
| 193 | .wait_icr_idle = noop_apic_wait_icr_idle, |
| 194 | .safe_wait_icr_idle = noop_safe_apic_wait_icr_idle, |
Tejun Heo | acb8bc0 | 2011-01-23 14:37:33 +0100 | [diff] [blame] | 195 | |
| 196 | #ifdef CONFIG_X86_32 |
| 197 | .x86_32_early_logical_apicid = noop_x86_32_early_logical_apicid, |
Tejun Heo | 89e5dc2 | 2011-01-23 14:37:38 +0100 | [diff] [blame] | 198 | .x86_32_numa_cpu_node = noop_x86_32_numa_cpu_node, |
Tejun Heo | acb8bc0 | 2011-01-23 14:37:33 +0100 | [diff] [blame] | 199 | #endif |
Cyrill Gorcunov | 9844ab1 | 2009-10-14 00:07:03 +0400 | [diff] [blame] | 200 | }; |