0001
0002
0003
0004
0005
0006
0007 #include <linux/cpumask.h>
0008 #include <linux/dmi.h>
0009 #include <linux/smp.h>
0010
0011 #include <asm/apic.h>
0012 #include <asm/io_apic.h>
0013
0014 #include "local.h"
0015
0016 static unsigned bigsmp_get_apic_id(unsigned long x)
0017 {
0018 return (x >> 24) & 0xFF;
0019 }
0020
0021 static int bigsmp_apic_id_registered(void)
0022 {
0023 return 1;
0024 }
0025
0026 static bool bigsmp_check_apicid_used(physid_mask_t *map, int apicid)
0027 {
0028 return false;
0029 }
0030
0031 static int bigsmp_early_logical_apicid(int cpu)
0032 {
0033
0034 return early_per_cpu(x86_cpu_to_apicid, cpu);
0035 }
0036
0037
0038
0039
0040
0041 static void bigsmp_init_apic_ldr(void)
0042 {
0043 }
0044
0045 static void bigsmp_setup_apic_routing(void)
0046 {
0047 printk(KERN_INFO
0048 "Enabling APIC mode: Physflat. Using %d I/O APICs\n",
0049 nr_ioapics);
0050 }
0051
0052 static int bigsmp_cpu_present_to_apicid(int mps_cpu)
0053 {
0054 if (mps_cpu < nr_cpu_ids)
0055 return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu);
0056
0057 return BAD_APICID;
0058 }
0059
0060 static void bigsmp_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
0061 {
0062
0063 physids_promote(0xFFL, retmap);
0064 }
0065
0066 static int bigsmp_check_phys_apicid_present(int phys_apicid)
0067 {
0068 return 1;
0069 }
0070
0071 static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
0072 {
0073 return cpuid_apic >> index_msb;
0074 }
0075
0076 static void bigsmp_send_IPI_allbutself(int vector)
0077 {
0078 default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector);
0079 }
0080
0081 static void bigsmp_send_IPI_all(int vector)
0082 {
0083 default_send_IPI_mask_sequence_phys(cpu_online_mask, vector);
0084 }
0085
0086 static int dmi_bigsmp;
0087
0088 static int hp_ht_bigsmp(const struct dmi_system_id *d)
0089 {
0090 printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
0091 dmi_bigsmp = 1;
0092
0093 return 0;
0094 }
0095
0096
0097 static const struct dmi_system_id bigsmp_dmi_table[] = {
0098 { hp_ht_bigsmp, "HP ProLiant DL760 G2",
0099 { DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
0100 DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
0101 }
0102 },
0103
0104 { hp_ht_bigsmp, "HP ProLiant DL740",
0105 { DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
0106 DMI_MATCH(DMI_BIOS_VERSION, "P47-"),
0107 }
0108 },
0109 { }
0110 };
0111
0112 static int probe_bigsmp(void)
0113 {
0114 if (def_to_bigsmp)
0115 dmi_bigsmp = 1;
0116 else
0117 dmi_check_system(bigsmp_dmi_table);
0118
0119 return dmi_bigsmp;
0120 }
0121
0122 static struct apic apic_bigsmp __ro_after_init = {
0123
0124 .name = "bigsmp",
0125 .probe = probe_bigsmp,
0126 .acpi_madt_oem_check = NULL,
0127 .apic_id_valid = default_apic_id_valid,
0128 .apic_id_registered = bigsmp_apic_id_registered,
0129
0130 .delivery_mode = APIC_DELIVERY_MODE_FIXED,
0131 .dest_mode_logical = false,
0132
0133 .disable_esr = 1,
0134
0135 .check_apicid_used = bigsmp_check_apicid_used,
0136 .init_apic_ldr = bigsmp_init_apic_ldr,
0137 .ioapic_phys_id_map = bigsmp_ioapic_phys_id_map,
0138 .setup_apic_routing = bigsmp_setup_apic_routing,
0139 .cpu_present_to_apicid = bigsmp_cpu_present_to_apicid,
0140 .apicid_to_cpu_present = physid_set_mask_of_physid,
0141 .check_phys_apicid_present = bigsmp_check_phys_apicid_present,
0142 .phys_pkg_id = bigsmp_phys_pkg_id,
0143
0144 .get_apic_id = bigsmp_get_apic_id,
0145 .set_apic_id = NULL,
0146
0147 .calc_dest_apicid = apic_default_calc_apicid,
0148
0149 .send_IPI = default_send_IPI_single_phys,
0150 .send_IPI_mask = default_send_IPI_mask_sequence_phys,
0151 .send_IPI_mask_allbutself = NULL,
0152 .send_IPI_allbutself = bigsmp_send_IPI_allbutself,
0153 .send_IPI_all = bigsmp_send_IPI_all,
0154 .send_IPI_self = default_send_IPI_self,
0155
0156 .inquire_remote_apic = default_inquire_remote_apic,
0157
0158 .read = native_apic_mem_read,
0159 .write = native_apic_mem_write,
0160 .eoi_write = native_apic_mem_write,
0161 .icr_read = native_apic_icr_read,
0162 .icr_write = native_apic_icr_write,
0163 .wait_icr_idle = native_apic_wait_icr_idle,
0164 .safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
0165
0166 .x86_32_early_logical_apicid = bigsmp_early_logical_apicid,
0167 };
0168
0169 void __init generic_bigsmp_probe(void)
0170 {
0171 unsigned int cpu;
0172
0173 if (!probe_bigsmp())
0174 return;
0175
0176 apic = &apic_bigsmp;
0177
0178 for_each_possible_cpu(cpu) {
0179 if (early_per_cpu(x86_cpu_to_logical_apicid,
0180 cpu) == BAD_APICID)
0181 continue;
0182 early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
0183 bigsmp_early_logical_apicid(cpu);
0184 }
0185
0186 pr_info("Overriding APIC driver with %s\n", apic_bigsmp.name);
0187 }
0188
0189 apic_driver(apic_bigsmp);