0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/cpumask.h>
0012 #include <linux/export.h>
0013 #include <linux/acpi.h>
0014
0015 #include <asm/jailhouse_para.h>
0016 #include <asm/apic.h>
0017
0018 #include "local.h"
0019
0020 static struct apic apic_physflat;
0021 static struct apic apic_flat;
0022
0023 struct apic *apic __ro_after_init = &apic_flat;
0024 EXPORT_SYMBOL_GPL(apic);
0025
0026 static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
0027 {
0028 return 1;
0029 }
0030
0031
0032
0033
0034
0035
0036
0037
0038 void flat_init_apic_ldr(void)
0039 {
0040 unsigned long val;
0041 unsigned long num, id;
0042
0043 num = smp_processor_id();
0044 id = 1UL << num;
0045 apic_write(APIC_DFR, APIC_DFR_FLAT);
0046 val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
0047 val |= SET_APIC_LOGICAL_ID(id);
0048 apic_write(APIC_LDR, val);
0049 }
0050
0051 static void _flat_send_IPI_mask(unsigned long mask, int vector)
0052 {
0053 unsigned long flags;
0054
0055 local_irq_save(flags);
0056 __default_send_IPI_dest_field(mask, vector, APIC_DEST_LOGICAL);
0057 local_irq_restore(flags);
0058 }
0059
0060 static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector)
0061 {
0062 unsigned long mask = cpumask_bits(cpumask)[0];
0063
0064 _flat_send_IPI_mask(mask, vector);
0065 }
0066
0067 static void
0068 flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
0069 {
0070 unsigned long mask = cpumask_bits(cpumask)[0];
0071 int cpu = smp_processor_id();
0072
0073 if (cpu < BITS_PER_LONG)
0074 __clear_bit(cpu, &mask);
0075
0076 _flat_send_IPI_mask(mask, vector);
0077 }
0078
0079 static unsigned int flat_get_apic_id(unsigned long x)
0080 {
0081 return (x >> 24) & 0xFF;
0082 }
0083
0084 static u32 set_apic_id(unsigned int id)
0085 {
0086 return (id & 0xFF) << 24;
0087 }
0088
0089 static unsigned int read_xapic_id(void)
0090 {
0091 return flat_get_apic_id(apic_read(APIC_ID));
0092 }
0093
0094 static int flat_apic_id_registered(void)
0095 {
0096 return physid_isset(read_xapic_id(), phys_cpu_present_map);
0097 }
0098
0099 static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
0100 {
0101 return initial_apic_id >> index_msb;
0102 }
0103
0104 static int flat_probe(void)
0105 {
0106 return 1;
0107 }
0108
0109 static struct apic apic_flat __ro_after_init = {
0110 .name = "flat",
0111 .probe = flat_probe,
0112 .acpi_madt_oem_check = flat_acpi_madt_oem_check,
0113 .apic_id_valid = default_apic_id_valid,
0114 .apic_id_registered = flat_apic_id_registered,
0115
0116 .delivery_mode = APIC_DELIVERY_MODE_FIXED,
0117 .dest_mode_logical = true,
0118
0119 .disable_esr = 0,
0120
0121 .check_apicid_used = NULL,
0122 .init_apic_ldr = flat_init_apic_ldr,
0123 .ioapic_phys_id_map = NULL,
0124 .setup_apic_routing = NULL,
0125 .cpu_present_to_apicid = default_cpu_present_to_apicid,
0126 .apicid_to_cpu_present = NULL,
0127 .check_phys_apicid_present = default_check_phys_apicid_present,
0128 .phys_pkg_id = flat_phys_pkg_id,
0129
0130 .get_apic_id = flat_get_apic_id,
0131 .set_apic_id = set_apic_id,
0132
0133 .calc_dest_apicid = apic_flat_calc_apicid,
0134
0135 .send_IPI = default_send_IPI_single,
0136 .send_IPI_mask = flat_send_IPI_mask,
0137 .send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself,
0138 .send_IPI_allbutself = default_send_IPI_allbutself,
0139 .send_IPI_all = default_send_IPI_all,
0140 .send_IPI_self = default_send_IPI_self,
0141
0142 .inquire_remote_apic = default_inquire_remote_apic,
0143
0144 .read = native_apic_mem_read,
0145 .write = native_apic_mem_write,
0146 .eoi_write = native_apic_mem_write,
0147 .icr_read = native_apic_icr_read,
0148 .icr_write = native_apic_icr_write,
0149 .wait_icr_idle = native_apic_wait_icr_idle,
0150 .safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
0151 };
0152
0153
0154
0155
0156
0157
0158 static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
0159 {
0160 #ifdef CONFIG_ACPI
0161
0162
0163
0164
0165
0166 if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
0167 (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
0168 printk(KERN_DEBUG "system APIC only can use physical flat");
0169 return 1;
0170 }
0171
0172 if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) {
0173 printk(KERN_DEBUG "IBM Summit detected, will use apic physical");
0174 return 1;
0175 }
0176 #endif
0177
0178 return 0;
0179 }
0180
0181 static void physflat_init_apic_ldr(void)
0182 {
0183
0184
0185
0186
0187
0188 }
0189
0190 static int physflat_probe(void)
0191 {
0192 if (apic == &apic_physflat || num_possible_cpus() > 8 ||
0193 jailhouse_paravirt())
0194 return 1;
0195
0196 return 0;
0197 }
0198
0199 static struct apic apic_physflat __ro_after_init = {
0200
0201 .name = "physical flat",
0202 .probe = physflat_probe,
0203 .acpi_madt_oem_check = physflat_acpi_madt_oem_check,
0204 .apic_id_valid = default_apic_id_valid,
0205 .apic_id_registered = flat_apic_id_registered,
0206
0207 .delivery_mode = APIC_DELIVERY_MODE_FIXED,
0208 .dest_mode_logical = false,
0209
0210 .disable_esr = 0,
0211
0212 .check_apicid_used = NULL,
0213 .init_apic_ldr = physflat_init_apic_ldr,
0214 .ioapic_phys_id_map = NULL,
0215 .setup_apic_routing = NULL,
0216 .cpu_present_to_apicid = default_cpu_present_to_apicid,
0217 .apicid_to_cpu_present = NULL,
0218 .check_phys_apicid_present = default_check_phys_apicid_present,
0219 .phys_pkg_id = flat_phys_pkg_id,
0220
0221 .get_apic_id = flat_get_apic_id,
0222 .set_apic_id = set_apic_id,
0223
0224 .calc_dest_apicid = apic_default_calc_apicid,
0225
0226 .send_IPI = default_send_IPI_single_phys,
0227 .send_IPI_mask = default_send_IPI_mask_sequence_phys,
0228 .send_IPI_mask_allbutself = default_send_IPI_mask_allbutself_phys,
0229 .send_IPI_allbutself = default_send_IPI_allbutself,
0230 .send_IPI_all = default_send_IPI_all,
0231 .send_IPI_self = default_send_IPI_self,
0232
0233 .inquire_remote_apic = default_inquire_remote_apic,
0234
0235 .read = native_apic_mem_read,
0236 .write = native_apic_mem_write,
0237 .eoi_write = native_apic_mem_write,
0238 .icr_read = native_apic_icr_read,
0239 .icr_write = native_apic_icr_write,
0240 .wait_icr_idle = native_apic_wait_icr_idle,
0241 .safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
0242 };
0243
0244
0245
0246
0247 apic_drivers(apic_physflat, apic_flat);