1 // SPDX-License-Identifier: GPL-2.0
3 * APIC driver for "bigsmp" xAPIC machines with more than 8 virtual CPUs.
5 * Drives the local APIC in "clustered mode".
7 #include <linux/cpumask.h>
15 static unsigned bigsmp_get_apic_id(unsigned long x
)
17 return (x
>> 24) & 0xFF;
20 static int bigsmp_apic_id_registered(void)
25 static bool bigsmp_check_apicid_used(physid_mask_t
*map
, int apicid
)
30 static int bigsmp_early_logical_apicid(int cpu
)
32 /* on bigsmp, logical apicid is the same as physical */
33 return early_per_cpu(x86_cpu_to_apicid
, cpu
);
37 * bigsmp enables physical destination mode
38 * and doesn't use LDR and DFR
40 static void bigsmp_init_apic_ldr(void)
44 static void bigsmp_setup_apic_routing(void)
47 "Enabling APIC mode: Physflat. Using %d I/O APICs\n",
51 static int bigsmp_cpu_present_to_apicid(int mps_cpu
)
53 if (mps_cpu
< nr_cpu_ids
)
54 return (int) per_cpu(x86_bios_cpu_apicid
, mps_cpu
);
59 static void bigsmp_ioapic_phys_id_map(physid_mask_t
*phys_map
, physid_mask_t
*retmap
)
61 /* For clustered we don't have a good way to do this yet - hack */
62 physids_promote(0xFFL
, retmap
);
65 static int bigsmp_check_phys_apicid_present(int phys_apicid
)
70 static int bigsmp_phys_pkg_id(int cpuid_apic
, int index_msb
)
72 return cpuid_apic
>> index_msb
;
75 static void bigsmp_send_IPI_allbutself(int vector
)
77 default_send_IPI_mask_allbutself_phys(cpu_online_mask
, vector
);
80 static void bigsmp_send_IPI_all(int vector
)
82 default_send_IPI_mask_sequence_phys(cpu_online_mask
, vector
);
85 static int dmi_bigsmp
; /* can be set by dmi scanners */
87 static int hp_ht_bigsmp(const struct dmi_system_id
*d
)
89 printk(KERN_NOTICE
"%s detected: force use of apic=bigsmp\n", d
->ident
);
96 static const struct dmi_system_id bigsmp_dmi_table
[] = {
97 { hp_ht_bigsmp
, "HP ProLiant DL760 G2",
98 { DMI_MATCH(DMI_BIOS_VENDOR
, "HP"),
99 DMI_MATCH(DMI_BIOS_VERSION
, "P44-"),
103 { hp_ht_bigsmp
, "HP ProLiant DL740",
104 { DMI_MATCH(DMI_BIOS_VENDOR
, "HP"),
105 DMI_MATCH(DMI_BIOS_VERSION
, "P47-"),
108 { } /* NULL entry stops DMI scanning */
111 static int probe_bigsmp(void)
116 dmi_check_system(bigsmp_dmi_table
);
121 static struct apic apic_bigsmp __ro_after_init
= {
124 .probe
= probe_bigsmp
,
125 .acpi_madt_oem_check
= NULL
,
126 .apic_id_valid
= default_apic_id_valid
,
127 .apic_id_registered
= bigsmp_apic_id_registered
,
129 .irq_delivery_mode
= dest_Fixed
,
130 /* phys delivery to target CPU: */
135 .check_apicid_used
= bigsmp_check_apicid_used
,
137 .init_apic_ldr
= bigsmp_init_apic_ldr
,
139 .ioapic_phys_id_map
= bigsmp_ioapic_phys_id_map
,
140 .setup_apic_routing
= bigsmp_setup_apic_routing
,
141 .cpu_present_to_apicid
= bigsmp_cpu_present_to_apicid
,
142 .apicid_to_cpu_present
= physid_set_mask_of_physid
,
143 .check_phys_apicid_present
= bigsmp_check_phys_apicid_present
,
144 .phys_pkg_id
= bigsmp_phys_pkg_id
,
146 .get_apic_id
= bigsmp_get_apic_id
,
149 .calc_dest_apicid
= apic_default_calc_apicid
,
151 .send_IPI
= default_send_IPI_single_phys
,
152 .send_IPI_mask
= default_send_IPI_mask_sequence_phys
,
153 .send_IPI_mask_allbutself
= NULL
,
154 .send_IPI_allbutself
= bigsmp_send_IPI_allbutself
,
155 .send_IPI_all
= bigsmp_send_IPI_all
,
156 .send_IPI_self
= default_send_IPI_self
,
158 .inquire_remote_apic
= default_inquire_remote_apic
,
160 .read
= native_apic_mem_read
,
161 .write
= native_apic_mem_write
,
162 .eoi_write
= native_apic_mem_write
,
163 .icr_read
= native_apic_icr_read
,
164 .icr_write
= native_apic_icr_write
,
165 .wait_icr_idle
= native_apic_wait_icr_idle
,
166 .safe_wait_icr_idle
= native_safe_apic_wait_icr_idle
,
168 .x86_32_early_logical_apicid
= bigsmp_early_logical_apicid
,
171 void __init
generic_bigsmp_probe(void)
180 for_each_possible_cpu(cpu
) {
181 if (early_per_cpu(x86_cpu_to_logical_apicid
,
184 early_per_cpu(x86_cpu_to_logical_apicid
, cpu
) =
185 bigsmp_early_logical_apicid(cpu
);
188 pr_info("Overriding APIC driver with %s\n", apic_bigsmp
.name
);
191 apic_driver(apic_bigsmp
);