1 // SPDX-License-Identifier: GPL-2.0-only
3 * Default generic APIC driver. This handles up to 8 CPUs.
5 * Copyright 2003 Andi Kleen, SuSE Labs.
7 * Generic x86 APIC driver probe layer.
9 #include <linux/export.h>
10 #include <linux/errno.h>
11 #include <linux/smp.h>
15 #include <asm/io_apic.h>
21 static u32
default_get_apic_id(u32 x
)
23 unsigned int ver
= GET_APIC_VERSION(apic_read(APIC_LVR
));
25 if (APIC_XAPIC(ver
) || boot_cpu_has(X86_FEATURE_EXTD_APICID
))
26 return (x
>> 24) & 0xFF;
28 return (x
>> 24) & 0x0F;
31 /* should be called last. */
32 static int probe_default(void)
37 static struct apic apic_default __ro_after_init
= {
40 .probe
= probe_default
,
42 .dest_mode_logical
= true,
46 .init_apic_ldr
= default_init_apic_ldr
,
47 .cpu_present_to_apicid
= default_cpu_present_to_apicid
,
50 .get_apic_id
= default_get_apic_id
,
52 .calc_dest_apicid
= apic_flat_calc_apicid
,
54 .send_IPI
= default_send_IPI_single
,
55 .send_IPI_mask
= default_send_IPI_mask_logical
,
56 .send_IPI_mask_allbutself
= default_send_IPI_mask_allbutself_logical
,
57 .send_IPI_allbutself
= default_send_IPI_allbutself
,
58 .send_IPI_all
= default_send_IPI_all
,
59 .send_IPI_self
= default_send_IPI_self
,
61 .read
= native_apic_mem_read
,
62 .write
= native_apic_mem_write
,
63 .eoi
= native_apic_mem_eoi
,
64 .icr_read
= native_apic_icr_read
,
65 .icr_write
= native_apic_icr_write
,
66 .wait_icr_idle
= apic_mem_wait_icr_idle
,
67 .safe_wait_icr_idle
= apic_mem_wait_icr_idle_timeout
,
70 apic_driver(apic_default
);
72 struct apic
*apic __ro_after_init
= &apic_default
;
73 EXPORT_SYMBOL_GPL(apic
);
75 static int cmdline_apic __initdata
;
76 static int __init
parse_apic(char *arg
)
83 for (drv
= __apicdrivers
; drv
< __apicdrivers_end
; drv
++) {
84 if (!strcmp((*drv
)->name
, arg
)) {
85 apic_install_driver(*drv
);
91 /* Parsed again by __setup for debug/verbose */
94 early_param("apic", parse_apic
);
96 void __init
x86_32_probe_bigsmp_early(void)
98 if (nr_cpu_ids
<= 8 || xen_pv_domain())
101 if (IS_ENABLED(CONFIG_X86_BIGSMP
)) {
102 switch (boot_cpu_data
.x86_vendor
) {
103 case X86_VENDOR_INTEL
:
104 if (!APIC_XAPIC(boot_cpu_apic_version
))
108 case X86_VENDOR_HYGON
:
110 if (apic_bigsmp_possible(cmdline_apic
))
115 pr_info("Limiting to 8 possible CPUs\n");
119 void __init
x86_32_install_bigsmp(void)
121 if (nr_cpu_ids
> 8 && !xen_pv_domain())
125 void __init
x86_32_probe_apic(void)
130 for (drv
= __apicdrivers
; drv
< __apicdrivers_end
; drv
++) {
131 if ((*drv
)->probe()) {
132 apic_install_driver(*drv
);
136 /* Not visible without early console */
137 if (drv
== __apicdrivers_end
)
138 panic("Didn't find an APIC driver");