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> 61b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu#include <linux/dmar.h> 71b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu 82d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha#include <asm/smp.h> 979deb8e511bd6fc8e40add4da75b19df085d9453Cyrill Gorcunov#include <asm/x2apic.h> 102d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 11ef1f87aa7ba6224bef1b750b3272ba281d8f43edSuresh Siddhaint x2apic_phys; 121b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu 131a8880a14270814dae0d226a2ad065d30587e60aSuresh Siddhastatic struct apic apic_x2apic_phys; 141a8880a14270814dae0d226a2ad065d30587e60aSuresh Siddha 151b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lustatic int set_x2apic_phys_mode(char *arg) 161b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu{ 171b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu x2apic_phys = 1; 181b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu return 0; 191b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu} 201b9b89e7f163336ad84200b66a17284dbf26acedYinghai Luearly_param("x2apic_phys", set_x2apic_phys_mode); 211b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu 22cb214ede7657db458fd0b2a25ea0b28dbf900ebcStoney Wangstatic bool x2apic_fadt_phys(void) 231b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu{ 24cb214ede7657db458fd0b2a25ea0b28dbf900ebcStoney Wang if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) && 25cb214ede7657db458fd0b2a25ea0b28dbf900ebcStoney Wang (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) { 26ea0dcf903e7d76aa5d483d876215fedcfdfe140fGreg Pearson printk(KERN_DEBUG "System requires x2apic physical mode\n"); 27cb214ede7657db458fd0b2a25ea0b28dbf900ebcStoney Wang return true; 28ea0dcf903e7d76aa5d483d876215fedcfdfe140fGreg Pearson } 29cb214ede7657db458fd0b2a25ea0b28dbf900ebcStoney Wang return false; 30cb214ede7657db458fd0b2a25ea0b28dbf900ebcStoney Wang} 31cb214ede7657db458fd0b2a25ea0b28dbf900ebcStoney Wang 32cb214ede7657db458fd0b2a25ea0b28dbf900ebcStoney Wangstatic int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) 33cb214ede7657db458fd0b2a25ea0b28dbf900ebcStoney Wang{ 34cb214ede7657db458fd0b2a25ea0b28dbf900ebcStoney Wang return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys()); 351b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu} 362d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 37a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddhastatic void 38a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha__x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest) 392d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha{ 402d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha unsigned long query_cpu; 41a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha unsigned long this_cpu; 42dac5f4121df3c39fdb2ea57acd669a0ae19e46f8Ingo Molnar unsigned long flags; 432d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 44ce4e240c279a31096f74afa6584a62d64a1ba8c8Suresh Siddha x2apic_wrmsr_fence(); 45ce4e240c279a31096f74afa6584a62d64a1ba8c8Suresh Siddha 462d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha local_irq_save(flags); 47a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha 48a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha this_cpu = smp_processor_id(); 49bcda016eddd7a8b374bb371473c821a91ff1d8ccMike Travis for_each_cpu(query_cpu, mask) { 50a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha if (apic_dest == APIC_DEST_ALLBUT && this_cpu == query_cpu) 51a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha continue; 522d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha __x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu), 532d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha vector, APIC_DEST_PHYSICAL); 542d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha } 552d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha local_irq_restore(flags); 562d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha} 572d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 58a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddhastatic void x2apic_send_IPI_mask(const struct cpumask *mask, int vector) 59a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha{ 60a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLINC); 61a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha} 62a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha 63dac5f4121df3c39fdb2ea57acd669a0ae19e46f8Ingo Molnarstatic void 64dac5f4121df3c39fdb2ea57acd669a0ae19e46f8Ingo Molnar x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector) 652d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha{ 66a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLBUT); 67e7986739a76cde5079da08809d8bbc6878387ae0Mike Travis} 682d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 69e7986739a76cde5079da08809d8bbc6878387ae0Mike Travisstatic void x2apic_send_IPI_allbutself(int vector) 70e7986739a76cde5079da08809d8bbc6878387ae0Mike Travis{ 71a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLBUT); 722d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha} 732d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 742d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddhastatic void x2apic_send_IPI_all(int vector) 752d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha{ 76a27d0b5e7d913b38880678ac05690f1dc737c4fdSuresh Siddha __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC); 772d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha} 782d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 794d08d97f5262dab4482af5bc91b30af4ca02269eJaswinder Singh Rajputstatic void init_x2apic_ldr(void) 802d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha{ 812d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha} 822d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha 839ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddhastatic int x2apic_phys_probe(void) 849ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha{ 85cb214ede7657db458fd0b2a25ea0b28dbf900ebcStoney Wang if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys())) 869ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha return 1; 879ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha 889ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha return apic == &apic_x2apic_phys; 899ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha} 909ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha 911a8880a14270814dae0d226a2ad065d30587e60aSuresh Siddhastatic struct apic apic_x2apic_phys = { 9205c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 9305c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .name = "physical x2apic", 949ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha .probe = x2apic_phys_probe, 9505c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .acpi_madt_oem_check = x2apic_acpi_madt_oem_check, 96b7157acf429e6aef690646ba964b9ebd25049ec2Steffen Persvold .apic_id_valid = x2apic_apic_id_valid, 9705c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .apic_id_registered = x2apic_apic_id_registered, 9805c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 99f8987a1093cc7a896137e264c24e04d4048e9f95Ingo Molnar .irq_delivery_mode = dest_Fixed, 1000b06e734bff7554c31eac4aad2fc9be4adb7c1c1Ingo Molnar .irq_dest_mode = 0, /* physical */ 10105c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 102bf721d3a3bc7a731add45c8078b142b494ab413eAlexander Gordeev .target_cpus = online_target_cpus, 10308125d3edab90644724652eedec3e219e3e0f2e7Ingo Molnar .disable_esr = 0, 104bdb1a9b62fc182d4da3143e346f7a0925d243352Ingo Molnar .dest_logical = 0, 10505c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .check_apicid_used = NULL, 10605c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 1079d8e10667624ea6411f04495aef1fa4a8a778ee8Alexander Gordeev .vector_allocation_domain = default_vector_allocation_domain, 10805c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .init_apic_ldr = init_x2apic_ldr, 10905c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 11005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .ioapic_phys_id_map = NULL, 11105c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .setup_apic_routing = NULL, 112a21769a4461801454930a06bc18bd8249cd9e993Ingo Molnar .cpu_present_to_apicid = default_cpu_present_to_apicid, 11305c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .apicid_to_cpu_present = NULL, 114a27a621001f4c3e57caf47feff4b014577fd01c6Ingo Molnar .check_phys_apicid_present = default_check_phys_apicid_present, 115d4c9a9f3d416cfa1f5ffbe09d864d069467fe693Ingo Molnar .phys_pkg_id = x2apic_phys_pkg_id, 11605c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 11779deb8e511bd6fc8e40add4da75b19df085d9453Cyrill Gorcunov .get_apic_id = x2apic_get_apic_id, 11879deb8e511bd6fc8e40add4da75b19df085d9453Cyrill Gorcunov .set_apic_id = x2apic_set_apic_id, 11905c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .apic_id_mask = 0xFFFFFFFFu, 12005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 1216398268d2bc454735f11e08705e858f9fdf5c750Alexander Gordeev .cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and, 12205c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 12305c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .send_IPI_mask = x2apic_send_IPI_mask, 12405c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .send_IPI_mask_allbutself = x2apic_send_IPI_mask_allbutself, 12505c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .send_IPI_allbutself = x2apic_send_IPI_allbutself, 12605c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .send_IPI_all = x2apic_send_IPI_all, 12705c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .send_IPI_self = x2apic_send_IPI_self, 12805c155c235c757329ec89ad591516538ed8352c0Ingo Molnar 129465822cfc8cb850ba76046965cc7b6fd1f8c3d73David Rientjes .wait_for_init_deassert = false, 13005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar .inquire_remote_apic = NULL, 131c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu 132c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .read = native_apic_msr_read, 133c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .write = native_apic_msr_write, 1340ab711ae6ab0db7696b43c74f9ba9de4d7fc1debMichael S. Tsirkin .eoi_write = native_apic_msr_eoi_write, 135c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .icr_read = native_x2apic_icr_read, 136c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .icr_write = native_x2apic_icr_write, 137c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .wait_icr_idle = native_x2apic_wait_icr_idle, 138c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu .safe_wait_icr_idle = native_safe_x2apic_wait_icr_idle, 1392d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha}; 140107e0e0cd85beeee05af7ea374fda14d037ee500Suresh Siddha 141107e0e0cd85beeee05af7ea374fda14d037ee500Suresh Siddhaapic_driver(apic_x2apic_phys); 142