x2apic_phys.c revision 107e0e0cd85beeee05af7ea374fda14d037ee500
12d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha#include <linux/threads.h> 22d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha#include <linux/cpumask.h> 32d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha#include <linux/string.h> 42d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha#include <linux/kernel.h> 52d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha#include <linux/ctype.h> 62d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha#include <linux/init.h> 71b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu#include <linux/dmar.h> 81b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu 92d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha#include <asm/smp.h> 1079deb8e511bd6fc8e40add4da75b19df085d9453Cyrill Gorcunov#include <asm/x2apic.h> 112d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 12ef1f87aa7ba6224bef1b750b3272ba281d8f43edSuresh Siddhaint x2apic_phys; 131b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu 141b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lustatic int set_x2apic_phys_mode(char *arg) 151b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu{ 161b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu x2apic_phys = 1; 171b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu return 0; 181b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu} 191b9b89e7f163336ad84200b66a17284dbf26acedYinghai Luearly_param("x2apic_phys", set_x2apic_phys_mode); 201b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu 213cfba0892585d4c8e7b4122b5dc0d206a76936deMarcin Slusarzstatic int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) 221b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu{ 23ef1f87aa7ba6224bef1b750b3272ba281d8f43edSuresh Siddha if (x2apic_phys) 24ef1f87aa7ba6224bef1b750b3272ba281d8f43edSuresh Siddha return x2apic_enabled(); 25ef1f87aa7ba6224bef1b750b3272ba281d8f43edSuresh Siddha else 26ef1f87aa7ba6224bef1b750b3272ba281d8f43edSuresh Siddha return 0; 271b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu} 282d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 29a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddhastatic void 30a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha__x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest) 312d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha{ 322d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha unsigned long query_cpu; 33a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha unsigned long this_cpu; 34dac5f4121df3c39fdb2ea57acd669a0ae19e46f8Ingo Molnar unsigned long flags; 352d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 36ce4e240c279a31096f74afa6584a62d64a1ba8c8Suresh Siddha x2apic_wrmsr_fence(); 37ce4e240c279a31096f74afa6584a62d64a1ba8c8Suresh Siddha 382d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha local_irq_save(flags); 39a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha 40a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha this_cpu = smp_processor_id(); 41bcda016eddd7a8b374bb371473c821a91ff1d8ccMike Travis for_each_cpu(query_cpu, mask) { 42a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha if (apic_dest == APIC_DEST_ALLBUT && this_cpu == query_cpu) 43a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha continue; 442d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu), 452d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha vector, APIC_DEST_PHYSICAL); 462d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha } 472d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha local_irq_restore(flags); 482d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha} 492d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 50a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddhastatic void x2apic_send_IPI_mask(const struct cpumask *mask, int vector) 51a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha{ 52a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLINC); 53a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha} 54a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha 55dac5f4121df3c39fdb2ea57acd669a0ae19e46f8Ingo Molnarstatic void 56dac5f4121df3c39fdb2ea57acd669a0ae19e46f8Ingo Molnar x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) 572d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha{ 58a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLBUT); 59e7986739a76cde5079da08809d8bbc6878387ae0Mike Travis} 602d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 61e7986739a76cde5079da08809d8bbc6878387ae0Mike Travisstatic void x2apic_send_IPI_allbutself(int vector) 62e7986739a76cde5079da08809d8bbc6878387ae0Mike Travis{ 63a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLBUT); 642d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha} 652d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 662d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddhastatic void x2apic_send_IPI_all(int vector) 672d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha{ 68a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC); 692d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha} 702d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 71bcda016eddd7a8b374bb371473c821a91ff1d8ccMike Travisstatic unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask) 722d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha{ 732d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha /* 742d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha * We're using fixed IRQ delivery, can only return one phys APIC ID. 752d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha * May as well be the first. 762d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha */ 77debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar int cpu = cpumask_first(cpumask); 78debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar 79e7986739a76cde5079da08809d8bbc6878387ae0Mike Travis if ((unsigned)cpu < nr_cpu_ids) 802d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha return per_cpu(x86_cpu_to_apicid, cpu); 812d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha else 822d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha return BAD_APICID; 832d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha} 842d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 85debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnarstatic unsigned int 86debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnarx2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask, 87debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar const struct cpumask *andmask) 8895d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis{ 8995d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis int cpu; 9095d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis 9195d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis /* 9295d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis * We're using fixed IRQ delivery, can only return one phys APIC ID. 9395d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis * May as well be the first. 9495d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis */ 95debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar for_each_cpu_and(cpu, cpumask, andmask) { 96a775a38b1353161a6d7af86b667d6523c12c1a37Mike Travis if (cpumask_test_cpu(cpu, cpu_online_mask)) 97a775a38b1353161a6d7af86b667d6523c12c1a37Mike Travis break; 98debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar } 99debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar 10018374d89e5fe96772102f44f535efb1198d9be08Suresh Siddha return per_cpu(x86_cpu_to_apicid, cpu); 10195d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis} 10295d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis 1034d08d97f5262dab4482af5bc91b30af4ca02269eJaswinder Singh Rajputstatic void init_x2apic_ldr(void) 1042d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha{ 1052d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha} 1062d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 1079ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddhastatic int x2apic_phys_probe(void) 1089ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha{ 1099ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha if (x2apic_mode && x2apic_phys) 1109ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha return 1; 1119ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha 1129ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha return apic == &apic_x2apic_phys; 1139ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha} 1149ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha 115be163a159b223e94b3180afdd47a8d468eb9a492Ingo Molnarstruct apic apic_x2apic_phys = { 11605c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 11705c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .name = "physical x2apic", 1189ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha .probe = x2apic_phys_probe, 11905c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, 12005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .apic_id_registered = x2apic_apic_id_registered, 12105c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 122f8987a1093cc7a896137e264c24e04d4048e9f95Ingo Molnar .irq_delivery_mode = dest_Fixed, 1230b06e734bff7554c31eac4aad2fc9be4adb7c1c1Ingo Molnar .irq_dest_mode = 0, /* physical */ 12405c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 12505c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .target_cpus = x2apic_target_cpus, 12608125d3edab90644724652eedec3e219e3e0f2e7Ingo Molnar .disable_esr = 0, 127bdb1a9b62fc182d4da3143e346f7a0925d243352Ingo Molnar .dest_logical = 0, 12805c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .check_apicid_used = NULL, 12905c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .check_apicid_present = NULL, 13005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 13105c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .vector_allocation_domain = x2apic_vector_allocation_domain, 13205c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .init_apic_ldr = init_x2apic_ldr, 13305c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 13405c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .ioapic_phys_id_map = NULL, 13505c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .setup_apic_routing = NULL, 13605c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .multi_timer_check = NULL, 137a21769a4461801454930a06bc18bd8249cd9e993Ingo Molnar .cpu_present_to_apicid = default_cpu_present_to_apicid, 13805c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .apicid_to_cpu_present = NULL, 13905c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .setup_portio_remap = NULL, 140a27a621001f4c3e57caf47feff4b014577fd01c6Ingo Molnar .check_phys_apicid_present = default_check_phys_apicid_present, 14105c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .enable_apic_mode = NULL, 142d4c9a9f3d416cfa1f5ffbe09d864d069467fe693Ingo Molnar .phys_pkg_id = x2apic_phys_pkg_id, 14305c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .mps_oem_check = NULL, 14405c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 14579deb8e511bd6fc8e40add4da75b19df085d9453Cyrill Gorcunov .get_apic_id = x2apic_get_apic_id, 14679deb8e511bd6fc8e40add4da75b19df085d9453Cyrill Gorcunov .set_apic_id = x2apic_set_apic_id, 14705c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .apic_id_mask = 0xFFFFFFFFu, 14805c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 14905c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .cpu_mask_to_apicid = x2apic_cpu_mask_to_apicid, 15005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .cpu_mask_to_apicid_and = x2apic_cpu_mask_to_apicid_and, 15105c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 15205c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .send_IPI_mask = x2apic_send_IPI_mask, 15305c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, 15405c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .send_IPI_allbutself = x2apic_send_IPI_allbutself, 15505c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .send_IPI_all = x2apic_send_IPI_all, 15605c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .send_IPI_self = x2apic_send_IPI_self, 15705c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 158abfa584c8df8b691cf18f51c7d4af27e5b32be4aIngo Molnar .trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW, 159abfa584c8df8b691cf18f51c7d4af27e5b32be4aIngo Molnar .trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH, 16005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .wait_for_init_deassert = NULL, 16105c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .smp_callin_clear_local_apic = NULL, 16205c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .inquire_remote_apic = NULL, 163c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu 164c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .read = native_apic_msr_read, 165c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .write = native_apic_msr_write, 166c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .icr_read = native_x2apic_icr_read, 167c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .icr_write = native_x2apic_icr_write, 168c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .wait_icr_idle = native_x2apic_wait_icr_idle, 169c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .safe_wait_icr_idle = native_safe_x2apic_wait_icr_idle, 1702d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha}; 171107e0e0cd85beeee05af7ea374fda14d037ee500Suresh Siddha 172107e0e0cd85beeee05af7ea374fda14d037ee500Suresh Siddhaapic_driver(apic_x2apic_phys); 173