blob: 77555f66c14d7747e8d42137c7d81f58076efe65 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Paolo Ciarrocchi637cba02008-02-20 00:18:52 +01002/*
Ingo Molnar77313192009-02-17 14:09:20 +01003 * APIC driver for "bigsmp" xAPIC machines with more than 8 virtual CPUs.
4 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Drives the local APIC in "clustered mode".
6 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007#include <linux/cpumask.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07008#include <linux/dmi.h>
Yinghai Lu4696ca52008-07-11 18:43:10 -07009#include <linux/smp.h>
Ingo Molnar9f4187f2009-01-28 19:19:12 +010010
Ingo Molnar77313192009-02-17 14:09:20 +010011#include <asm/apic.h>
Ingo Molnar13c01132020-08-06 14:34:32 +020012#include <asm/io_apic.h>
Thomas Gleixner8b542da2019-07-22 20:47:12 +020013
Thomas Gleixnerc94f0712019-07-22 20:47:14 +020014#include "local.h"
Ingo Molnar9f4187f2009-01-28 19:19:12 +010015
Jiri Slaby9694cd62009-03-02 10:53:55 +010016static unsigned bigsmp_get_apic_id(unsigned long x)
Ingo Molnar9f4187f2009-01-28 19:19:12 +010017{
18 return (x >> 24) & 0xFF;
19}
20
Jiri Slaby9694cd62009-03-02 10:53:55 +010021static int bigsmp_apic_id_registered(void)
Ingo Molnar9f4187f2009-01-28 19:19:12 +010022{
23 return 1;
24}
25
Thomas Gleixner57e0aa42017-09-13 23:29:18 +020026static bool bigsmp_check_apicid_used(physid_mask_t *map, int apicid)
Ingo Molnar9f4187f2009-01-28 19:19:12 +010027{
Thomas Gleixner57e0aa42017-09-13 23:29:18 +020028 return false;
Ingo Molnar9f4187f2009-01-28 19:19:12 +010029}
30
Tejun Heo12bf24a2011-01-23 14:37:35 +010031static int bigsmp_early_logical_apicid(int cpu)
32{
33 /* on bigsmp, logical apicid is the same as physical */
34 return early_per_cpu(x86_cpu_to_apicid, cpu);
35}
36
Ingo Molnar9f4187f2009-01-28 19:19:12 +010037/*
Bandan Dasbae3a8d2019-08-26 06:15:12 -040038 * bigsmp enables physical destination mode
39 * and doesn't use LDR and DFR
Ingo Molnar9f4187f2009-01-28 19:19:12 +010040 */
Jiri Slaby9694cd62009-03-02 10:53:55 +010041static void bigsmp_init_apic_ldr(void)
Ingo Molnar9f4187f2009-01-28 19:19:12 +010042{
Ingo Molnar9f4187f2009-01-28 19:19:12 +010043}
44
Jiri Slaby9694cd62009-03-02 10:53:55 +010045static void bigsmp_setup_apic_routing(void)
Ingo Molnar9f4187f2009-01-28 19:19:12 +010046{
Ingo Molnar77313192009-02-17 14:09:20 +010047 printk(KERN_INFO
48 "Enabling APIC mode: Physflat. Using %d I/O APICs\n",
49 nr_ioapics);
Ingo Molnar9f4187f2009-01-28 19:19:12 +010050}
51
Jiri Slaby9694cd62009-03-02 10:53:55 +010052static int bigsmp_cpu_present_to_apicid(int mps_cpu)
Ingo Molnar9f4187f2009-01-28 19:19:12 +010053{
54 if (mps_cpu < nr_cpu_ids)
55 return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu);
56
57 return BAD_APICID;
58}
59
Cyrill Gorcunov7abc0752009-11-10 01:06:59 +030060static void bigsmp_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
Ingo Molnar9f4187f2009-01-28 19:19:12 +010061{
62 /* For clustered we don't have a good way to do this yet - hack */
Cyrill Gorcunov7abc0752009-11-10 01:06:59 +030063 physids_promote(0xFFL, retmap);
Ingo Molnar9f4187f2009-01-28 19:19:12 +010064}
65
Thomas Gleixnere11dada2009-08-31 15:18:40 +020066static int bigsmp_check_phys_apicid_present(int phys_apicid)
Ingo Molnar9f4187f2009-01-28 19:19:12 +010067{
68 return 1;
69}
70
Jiri Slaby9694cd62009-03-02 10:53:55 +010071static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
Ingo Molnar9f4187f2009-01-28 19:19:12 +010072{
73 return cpuid_apic >> index_msb;
74}
75
Jiri Slaby9694cd62009-03-02 10:53:55 +010076static void bigsmp_send_IPI_allbutself(int vector)
Ingo Molnar9f4187f2009-01-28 19:19:12 +010077{
Yinghai Lu43f39892009-01-29 19:31:49 -080078 default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector);
Ingo Molnar9f4187f2009-01-28 19:19:12 +010079}
80
Jiri Slaby9694cd62009-03-02 10:53:55 +010081static void bigsmp_send_IPI_all(int vector)
Ingo Molnar9f4187f2009-01-28 19:19:12 +010082{
Thomas Gleixner500bd022015-11-04 22:57:03 +000083 default_send_IPI_mask_sequence_phys(cpu_online_mask, vector);
Ingo Molnar9f4187f2009-01-28 19:19:12 +010084}
Linus Torvalds1da177e2005-04-16 15:20:36 -070085
86static int dmi_bigsmp; /* can be set by dmi scanners */
87
Jeff Garzik18552562007-10-03 15:15:40 -040088static int hp_ht_bigsmp(const struct dmi_system_id *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -070089{
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
91 dmi_bigsmp = 1;
Ingo Molnar77313192009-02-17 14:09:20 +010092
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 return 0;
94}
95
96
Jeff Garzik18552562007-10-03 15:15:40 -040097static const struct dmi_system_id bigsmp_dmi_table[] = {
Paolo Ciarrocchi637cba02008-02-20 00:18:52 +010098 { hp_ht_bigsmp, "HP ProLiant DL760 G2",
Ingo Molnar77313192009-02-17 14:09:20 +010099 { DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
100 DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
101 }
Paolo Ciarrocchi637cba02008-02-20 00:18:52 +0100102 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Paolo Ciarrocchi637cba02008-02-20 00:18:52 +0100104 { hp_ht_bigsmp, "HP ProLiant DL740",
Ingo Molnar77313192009-02-17 14:09:20 +0100105 { DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
106 DMI_MATCH(DMI_BIOS_VERSION, "P47-"),
107 }
Paolo Ciarrocchi637cba02008-02-20 00:18:52 +0100108 },
Ingo Molnar77313192009-02-17 14:09:20 +0100109 { } /* NULL entry stops DMI scanning */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110};
111
William Lee Irwin IIIaf669c92007-05-23 13:58:23 -0700112static int probe_bigsmp(void)
Paolo Ciarrocchi637cba02008-02-20 00:18:52 +0100113{
Venkatesh Pallipadi911a62d2005-09-03 15:56:31 -0700114 if (def_to_bigsmp)
Yinghai Lue0da3362008-06-08 18:29:22 -0700115 dmi_bigsmp = 1;
Venkatesh Pallipadi911a62d2005-09-03 15:56:31 -0700116 else
117 dmi_check_system(bigsmp_dmi_table);
Ingo Molnar77313192009-02-17 14:09:20 +0100118
Paolo Ciarrocchi637cba02008-02-20 00:18:52 +0100119 return dmi_bigsmp;
120}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
Kees Cook404f6aa2016-08-08 16:29:06 -0700122static struct apic apic_bigsmp __ro_after_init = {
Ingo Molnard26b6d62009-01-28 03:32:03 +0100123
124 .name = "bigsmp",
125 .probe = probe_bigsmp,
Ingo Molnar306db032009-01-28 03:43:47 +0100126 .acpi_madt_oem_check = NULL,
Daniel J Bluemanfa630302012-03-14 15:17:34 +0800127 .apic_id_valid = default_apic_id_valid,
Ingo Molnar7ed248d2009-01-28 03:43:47 +0100128 .apic_id_registered = bigsmp_apic_id_registered,
Ingo Molnard26b6d62009-01-28 03:32:03 +0100129
Thomas Gleixner72161292020-10-24 22:35:05 +0100130 .delivery_mode = APIC_DELIVERY_MODE_FIXED,
Thomas Gleixner8c449632020-10-24 22:35:08 +0100131 .dest_mode_logical = false,
Ingo Molnard26b6d62009-01-28 03:32:03 +0100132
Ingo Molnar08125d32009-01-28 05:08:44 +0100133 .disable_esr = 1,
Thomas Gleixnere57d04e2020-10-24 22:35:07 +0100134
Ingo Molnard1d7cae2009-01-28 05:41:42 +0100135 .check_apicid_used = bigsmp_check_apicid_used,
Ingo Molnara5c43292009-01-28 06:50:47 +0100136 .init_apic_ldr = bigsmp_init_apic_ldr,
Ingo Molnard190cb82009-01-28 06:50:47 +0100137 .ioapic_phys_id_map = bigsmp_ioapic_phys_id_map,
Ingo Molnar72ce0162009-01-28 06:50:47 +0100138 .setup_apic_routing = bigsmp_setup_apic_routing,
Ingo Molnara21769a42009-01-28 06:50:47 +0100139 .cpu_present_to_apicid = bigsmp_cpu_present_to_apicid,
Cyrill Gorcunov7abc0752009-11-10 01:06:59 +0300140 .apicid_to_cpu_present = physid_set_mask_of_physid,
Ingo Molnara27a6212009-01-28 12:43:18 +0100141 .check_phys_apicid_present = bigsmp_check_phys_apicid_present,
Ingo Molnarcb8cc442009-01-28 13:24:54 +0100142 .phys_pkg_id = bigsmp_phys_pkg_id,
Ingo Molnard26b6d62009-01-28 03:32:03 +0100143
Ingo Molnarca6c8ed2009-01-28 14:08:38 +0100144 .get_apic_id = bigsmp_get_apic_id,
Ingo Molnard26b6d62009-01-28 03:32:03 +0100145 .set_apic_id = NULL,
Ingo Molnard26b6d62009-01-28 03:32:03 +0100146
Thomas Gleixner9f9e3bb2017-09-13 23:29:37 +0200147 .calc_dest_apicid = apic_default_calc_apicid,
Ingo Molnard26b6d62009-01-28 03:32:03 +0100148
Thomas Gleixner5789a122015-11-04 22:57:04 +0000149 .send_IPI = default_send_IPI_single_phys,
Thomas Gleixner500bd022015-11-04 22:57:03 +0000150 .send_IPI_mask = default_send_IPI_mask_sequence_phys,
Ingo Molnard26b6d62009-01-28 03:32:03 +0100151 .send_IPI_mask_allbutself = NULL,
Ingo Molnardac5f412009-01-28 15:42:24 +0100152 .send_IPI_allbutself = bigsmp_send_IPI_allbutself,
153 .send_IPI_all = bigsmp_send_IPI_all,
Ingo Molnar6b64ee02009-01-30 23:42:18 +0100154 .send_IPI_self = default_send_IPI_self,
Ingo Molnard26b6d62009-01-28 03:32:03 +0100155
Ingo Molnar25dc0042009-01-28 16:31:52 +0100156 .inquire_remote_apic = default_inquire_remote_apic,
Yinghai Luc1eeb2d2009-02-16 23:02:14 -0800157
158 .read = native_apic_mem_read,
159 .write = native_apic_mem_write,
Michael S. Tsirkin2a431952012-05-16 19:03:52 +0300160 .eoi_write = native_apic_mem_write,
Yinghai Luc1eeb2d2009-02-16 23:02:14 -0800161 .icr_read = native_apic_icr_read,
162 .icr_write = native_apic_icr_write,
163 .wait_icr_idle = native_apic_wait_icr_idle,
164 .safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
Tejun Heoacb8bc02011-01-23 14:37:33 +0100165
Tejun Heo12bf24a2011-01-23 14:37:35 +0100166 .x86_32_early_logical_apicid = bigsmp_early_logical_apicid,
Ingo Molnard26b6d62009-01-28 03:32:03 +0100167};
Suresh Siddha107e0e02011-05-20 17:51:17 -0700168
Jan Beulich838312b2011-09-28 16:44:54 +0100169void __init generic_bigsmp_probe(void)
Suresh Siddha69c252f2011-05-20 17:51:19 -0700170{
Jan Beulich838312b2011-09-28 16:44:54 +0100171 unsigned int cpu;
Suresh Siddha69c252f2011-05-20 17:51:19 -0700172
Jan Beulich838312b2011-09-28 16:44:54 +0100173 if (!probe_bigsmp())
174 return;
175
176 apic = &apic_bigsmp;
177
178 for_each_possible_cpu(cpu) {
179 if (early_per_cpu(x86_cpu_to_logical_apicid,
180 cpu) == BAD_APICID)
181 continue;
182 early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
183 bigsmp_early_logical_apicid(cpu);
184 }
185
186 pr_info("Overriding APIC driver with %s\n", apic_bigsmp.name);
Suresh Siddha69c252f2011-05-20 17:51:19 -0700187}
188
Suresh Siddha107e0e02011-05-20 17:51:17 -0700189apic_driver(apic_bigsmp);