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