x2apic_phys.c revision 0ab711ae6ab0db7696b43c74f9ba9de4d7fc1deb
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
141a8880a14270814dae0d226a2ad065d30587e60aSuresh Siddhastatic struct apic apic_x2apic_phys;
151a8880a14270814dae0d226a2ad065d30587e60aSuresh Siddha
161b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lustatic int set_x2apic_phys_mode(char *arg)
171b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu{
181b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu	x2apic_phys = 1;
191b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu	return 0;
201b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu}
211b9b89e7f163336ad84200b66a17284dbf26acedYinghai Luearly_param("x2apic_phys", set_x2apic_phys_mode);
221b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu
233cfba0892585d4c8e7b4122b5dc0d206a76936deMarcin Slusarzstatic int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
241b9b89e7f163336ad84200b66a17284dbf26acedYinghai Lu{
25ef1f87aa7ba6224bef1b750b3272ba281d8f43edSuresh Siddha	if (x2apic_phys)
26ef1f87aa7ba6224bef1b750b3272ba281d8f43edSuresh Siddha		return x2apic_enabled();
27ea0dcf903e7d76aa5d483d876215fedcfdfe140fGreg Pearson	else if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) &&
28ea0dcf903e7d76aa5d483d876215fedcfdfe140fGreg Pearson		(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL) &&
29ea0dcf903e7d76aa5d483d876215fedcfdfe140fGreg Pearson		x2apic_enabled()) {
30ea0dcf903e7d76aa5d483d876215fedcfdfe140fGreg Pearson		printk(KERN_DEBUG "System requires x2apic physical mode\n");
31ea0dcf903e7d76aa5d483d876215fedcfdfe140fGreg Pearson		return 1;
32ea0dcf903e7d76aa5d483d876215fedcfdfe140fGreg Pearson	}
33ef1f87aa7ba6224bef1b750b3272ba281d8f43edSuresh Siddha	else
34ef1f87aa7ba6224bef1b750b3272ba281d8f43edSuresh Siddha		return 0;
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
79bcda016eddd7a8b374bb371473c821a91ff1d8ccMike Travisstatic unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask)
802d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha{
812d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha	/*
822d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha	 * We're using fixed IRQ delivery, can only return one phys APIC ID.
832d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha	 * May as well be the first.
842d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha	 */
85debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar	int cpu = cpumask_first(cpumask);
86debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar
87e7986739a76cde5079da08809d8bbc6878387ae0Mike Travis	if ((unsigned)cpu < nr_cpu_ids)
882d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha		return per_cpu(x86_cpu_to_apicid, cpu);
892d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha	else
902d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha		return BAD_APICID;
912d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha}
922d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha
93debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnarstatic unsigned int
94debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnarx2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
95debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar			      const struct cpumask *andmask)
9695d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis{
9795d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis	int cpu;
9895d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis
9995d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis	/*
10095d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis	 * We're using fixed IRQ delivery, can only return one phys APIC ID.
10195d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis	 * May as well be the first.
10295d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis	 */
103debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar	for_each_cpu_and(cpu, cpumask, andmask) {
104a775a38b1353161a6d7af86b667d6523c12c1a37Mike Travis		if (cpumask_test_cpu(cpu, cpu_online_mask))
105a775a38b1353161a6d7af86b667d6523c12c1a37Mike Travis			break;
106debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar	}
107debccb3e77be52cfc26c5a99e123c114c5c72aebIngo Molnar
10818374d89e5fe96772102f44f535efb1198d9be08Suresh Siddha	return per_cpu(x86_cpu_to_apicid, cpu);
10995d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis}
11095d313cf1c1ecedc8bec5727b09bdacbf67dfc45Mike Travis
1114d08d97f5262dab4482af5bc91b30af4ca02269eJaswinder Singh Rajputstatic void init_x2apic_ldr(void)
1122d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha{
1132d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha}
1142d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha
1159ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddhastatic int x2apic_phys_probe(void)
1169ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha{
1179ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha	if (x2apic_mode && x2apic_phys)
1189ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha		return 1;
1199ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha
1209ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha	return apic == &apic_x2apic_phys;
1219ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha}
1229ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha
1231a8880a14270814dae0d226a2ad065d30587e60aSuresh Siddhastatic struct apic apic_x2apic_phys = {
12405c155c235c757329ec89ad591516538ed8352c0Ingo Molnar
12505c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.name				= "physical x2apic",
1269ebd680bd029a9fc47399ca61c950f8b6730ac40Suresh Siddha	.probe				= x2apic_phys_probe,
12705c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.acpi_madt_oem_check		= x2apic_acpi_madt_oem_check,
128b7157acf429e6aef690646ba964b9ebd25049ec2Steffen Persvold	.apic_id_valid			= x2apic_apic_id_valid,
12905c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.apic_id_registered		= x2apic_apic_id_registered,
13005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar
131f8987a1093cc7a896137e264c24e04d4048e9f95Ingo Molnar	.irq_delivery_mode		= dest_Fixed,
1320b06e734bff7554c31eac4aad2fc9be4adb7c1c1Ingo Molnar	.irq_dest_mode			= 0, /* physical */
13305c155c235c757329ec89ad591516538ed8352c0Ingo Molnar
13405c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.target_cpus			= x2apic_target_cpus,
13508125d3edab90644724652eedec3e219e3e0f2e7Ingo Molnar	.disable_esr			= 0,
136bdb1a9b62fc182d4da3143e346f7a0925d243352Ingo Molnar	.dest_logical			= 0,
13705c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.check_apicid_used		= NULL,
13805c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.check_apicid_present		= NULL,
13905c155c235c757329ec89ad591516538ed8352c0Ingo Molnar
14005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.vector_allocation_domain	= x2apic_vector_allocation_domain,
14105c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.init_apic_ldr			= init_x2apic_ldr,
14205c155c235c757329ec89ad591516538ed8352c0Ingo Molnar
14305c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.ioapic_phys_id_map		= NULL,
14405c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.setup_apic_routing		= NULL,
14505c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.multi_timer_check		= NULL,
146a21769a4461801454930a06bc18bd8249cd9e993Ingo Molnar	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
14705c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.apicid_to_cpu_present		= NULL,
14805c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.setup_portio_remap		= NULL,
149a27a621001f4c3e57caf47feff4b014577fd01c6Ingo Molnar	.check_phys_apicid_present	= default_check_phys_apicid_present,
15005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.enable_apic_mode		= NULL,
151d4c9a9f3d416cfa1f5ffbe09d864d069467fe693Ingo Molnar	.phys_pkg_id			= x2apic_phys_pkg_id,
15205c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.mps_oem_check			= NULL,
15305c155c235c757329ec89ad591516538ed8352c0Ingo Molnar
15479deb8e511bd6fc8e40add4da75b19df085d9453Cyrill Gorcunov	.get_apic_id			= x2apic_get_apic_id,
15579deb8e511bd6fc8e40add4da75b19df085d9453Cyrill Gorcunov	.set_apic_id			= x2apic_set_apic_id,
15605c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.apic_id_mask			= 0xFFFFFFFFu,
15705c155c235c757329ec89ad591516538ed8352c0Ingo Molnar
15805c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.cpu_mask_to_apicid		= x2apic_cpu_mask_to_apicid,
15905c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.cpu_mask_to_apicid_and		= x2apic_cpu_mask_to_apicid_and,
16005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar
16105c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.send_IPI_mask			= x2apic_send_IPI_mask,
16205c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.send_IPI_mask_allbutself	= x2apic_send_IPI_mask_allbutself,
16305c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.send_IPI_allbutself		= x2apic_send_IPI_allbutself,
16405c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.send_IPI_all			= x2apic_send_IPI_all,
16505c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.send_IPI_self			= x2apic_send_IPI_self,
16605c155c235c757329ec89ad591516538ed8352c0Ingo Molnar
167abfa584c8df8b691cf18f51c7d4af27e5b32be4aIngo Molnar	.trampoline_phys_low		= DEFAULT_TRAMPOLINE_PHYS_LOW,
168abfa584c8df8b691cf18f51c7d4af27e5b32be4aIngo Molnar	.trampoline_phys_high		= DEFAULT_TRAMPOLINE_PHYS_HIGH,
16905c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.wait_for_init_deassert		= NULL,
17005c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.smp_callin_clear_local_apic	= NULL,
17105c155c235c757329ec89ad591516538ed8352c0Ingo Molnar	.inquire_remote_apic		= NULL,
172c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu
173c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu	.read				= native_apic_msr_read,
174c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu	.write				= native_apic_msr_write,
1750ab711ae6ab0db7696b43c74f9ba9de4d7fc1debMichael S. Tsirkin	.eoi_write			= native_apic_msr_eoi_write,
176c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu	.icr_read			= native_x2apic_icr_read,
177c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu	.icr_write			= native_x2apic_icr_write,
178c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu	.wait_icr_idle			= native_x2apic_wait_icr_idle,
179c1eeb2de41d7015678bdd412b48a5f071b84e29aYinghai Lu	.safe_wait_icr_idle		= native_safe_x2apic_wait_icr_idle,
1802d9579a124d746a3e0e0ba45e57d80800ee80807Suresh Siddha};
181107e0e0cd85beeee05af7ea374fda14d037ee500Suresh Siddha
182107e0e0cd85beeee05af7ea374fda14d037ee500Suresh Siddhaapic_driver(apic_x2apic_phys);
183