x2apic_phys.c 3.7 KB
Newer Older
1 2 3 4 5
#include <linux/threads.h>
#include <linux/cpumask.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/ctype.h>
6 7
#include <linux/dmar.h>

8
#include <asm/smp.h>
9
#include <asm/x2apic.h>
10

11
int x2apic_phys;
12

13 14
static struct apic apic_x2apic_phys;

15 16 17 18 19 20 21
static int set_x2apic_phys_mode(char *arg)
{
	x2apic_phys = 1;
	return 0;
}
early_param("x2apic_phys", set_x2apic_phys_mode);

22
static bool x2apic_fadt_phys(void)
23
{
24
#ifdef CONFIG_ACPI
25 26
	if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) &&
		(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
27
		printk(KERN_DEBUG "System requires x2apic physical mode\n");
28
		return true;
29
	}
30
#endif
31 32 33 34 35 36
	return false;
}

static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
	return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys());
37
}
38

39 40 41 42 43 44 45 46
static void x2apic_send_IPI(int cpu, int vector)
{
	u32 dest = per_cpu(x86_cpu_to_apicid, cpu);

	x2apic_wrmsr_fence();
	__x2apic_send_IPI_dest(dest, vector, APIC_DEST_PHYSICAL);
}

47 48
static void
__x2apic_send_IPI_mask(const struct cpumask *mask, int vector, int apic_dest)
49 50
{
	unsigned long query_cpu;
51
	unsigned long this_cpu;
52
	unsigned long flags;
53

54 55
	x2apic_wrmsr_fence();

56
	local_irq_save(flags);
57 58

	this_cpu = smp_processor_id();
59
	for_each_cpu(query_cpu, mask) {
60 61
		if (apic_dest == APIC_DEST_ALLBUT && this_cpu == query_cpu)
			continue;
62 63 64 65 66 67
		__x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu),
				       vector, APIC_DEST_PHYSICAL);
	}
	local_irq_restore(flags);
}

68 69 70 71 72
static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector)
{
	__x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLINC);
}

73 74
static void
 x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
75
{
76
	__x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLBUT);
77
}
78

79 80
static void x2apic_send_IPI_allbutself(int vector)
{
81
	__x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLBUT);
82 83 84 85
}

static void x2apic_send_IPI_all(int vector)
{
86
	__x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC);
87 88
}

89
static void init_x2apic_ldr(void)
90 91 92
{
}

93 94
static int x2apic_phys_probe(void)
{
95
	if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys()))
96 97 98 99 100
		return 1;

	return apic == &apic_x2apic_phys;
}

101
static struct apic apic_x2apic_phys __ro_after_init = {
I
Ingo Molnar 已提交
102 103

	.name				= "physical x2apic",
104
	.probe				= x2apic_phys_probe,
I
Ingo Molnar 已提交
105
	.acpi_madt_oem_check		= x2apic_acpi_madt_oem_check,
106
	.apic_id_valid			= x2apic_apic_id_valid,
I
Ingo Molnar 已提交
107 108
	.apic_id_registered		= x2apic_apic_id_registered,

109
	.irq_delivery_mode		= dest_Fixed,
110
	.irq_dest_mode			= 0, /* physical */
I
Ingo Molnar 已提交
111

112
	.target_cpus			= online_target_cpus,
113
	.disable_esr			= 0,
114
	.dest_logical			= 0,
I
Ingo Molnar 已提交
115 116
	.check_apicid_used		= NULL,

117
	.vector_allocation_domain	= default_vector_allocation_domain,
I
Ingo Molnar 已提交
118 119 120 121
	.init_apic_ldr			= init_x2apic_ldr,

	.ioapic_phys_id_map		= NULL,
	.setup_apic_routing		= NULL,
122
	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
I
Ingo Molnar 已提交
123
	.apicid_to_cpu_present		= NULL,
124
	.check_phys_apicid_present	= default_check_phys_apicid_present,
I
Ingo Molnar 已提交
125
	.phys_pkg_id			= x2apic_phys_pkg_id,
I
Ingo Molnar 已提交
126

127 128
	.get_apic_id			= x2apic_get_apic_id,
	.set_apic_id			= x2apic_set_apic_id,
I
Ingo Molnar 已提交
129

130
	.cpu_mask_to_apicid		= default_cpu_mask_to_apicid,
I
Ingo Molnar 已提交
131

132
	.send_IPI			= x2apic_send_IPI,
I
Ingo Molnar 已提交
133 134 135 136 137 138 139
	.send_IPI_mask			= x2apic_send_IPI_mask,
	.send_IPI_mask_allbutself	= x2apic_send_IPI_mask_allbutself,
	.send_IPI_allbutself		= x2apic_send_IPI_allbutself,
	.send_IPI_all			= x2apic_send_IPI_all,
	.send_IPI_self			= x2apic_send_IPI_self,

	.inquire_remote_apic		= NULL,
Y
Yinghai Lu 已提交
140 141 142

	.read				= native_apic_msr_read,
	.write				= native_apic_msr_write,
143
	.eoi_write			= native_apic_msr_eoi_write,
Y
Yinghai Lu 已提交
144 145 146 147
	.icr_read			= native_x2apic_icr_read,
	.icr_write			= native_x2apic_icr_write,
	.wait_icr_idle			= native_x2apic_wait_icr_idle,
	.safe_wait_icr_idle		= native_safe_x2apic_wait_icr_idle,
148
};
149 150

apic_driver(apic_x2apic_phys);