32 #include <linux/kernel.h>
34 #include <linux/module.h>
35 #include <linux/string.h>
42 #include <asm/processor.h>
43 #include <asm/fixmap.h>
46 #include <asm/setup.h>
68 static int mpc_record;
70 static struct mpc_trans *translation_table[MAX_MPC_ENTRY];
77 static inline void numaq_register_node(
int node,
struct sys_cfg_data *scd)
79 struct eachquadmem *eq = scd->eq +
node;
80 u64 start = (
u64)(eq->hi_shrd_mem_start - eq->priv_mem_size) << 20;
81 u64 end = (
u64)(eq->hi_shrd_mem_start + eq->hi_shrd_mem_size) << 20;
95 static void __init smp_dump_qct(
void)
97 struct sys_cfg_data *scd;
100 scd = (
void *)
__va(SYS_CFG_DATA_PRIV_ADDR);
103 if (scd->quads_present31_0 & (1 << node))
104 numaq_register_node(node, scd);
119 static void __init numaq_tsc_init(
void)
124 static inline int generate_logical_apicid(
int quad,
int phys_apicid)
126 return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1);
130 static int mpc_apic_id(
struct mpc_cpu *
m)
132 int quad = translation_table[mpc_record]->
trans_quad;
133 int logical_apicid = generate_logical_apicid(quad, m->
apicid);
136 "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n",
139 m->
apicver, quad, logical_apicid);
141 return logical_apicid;
145 static void mpc_oem_bus_info(
struct mpc_bus *
m,
char *
name)
147 int quad = translation_table[mpc_record]->
trans_quad;
148 int local = translation_table[mpc_record]->
trans_local;
157 static void mpc_oem_pci_bus(
struct mpc_bus *
m)
159 int quad = translation_table[mpc_record]->
trans_quad;
160 int local = translation_table[mpc_record]->
trans_local;
170 static void numaq_mpc_record(
unsigned int mode)
181 "Translation: record %d, type %d, quad %d, global %d, local %d\n",
185 if (mpc_record >= MAX_MPC_ENTRY)
188 translation_table[mpc_record] =
m;
194 static int __init mpf_checksum(
unsigned char *
mp,
int len)
210 int count =
sizeof(*oemtable);
211 unsigned char *oemptr = ((
unsigned char *)oemtable) +
count;
215 "Found an OEM MPC table at %8p - parsing it...\n", oemtable);
219 "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
225 if (mpf_checksum((
unsigned char *)oemtable, oemtable->
length)) {
230 while (count < oemtable->
length) {
236 MP_translation_info(m);
237 oemptr +=
sizeof(*m);
244 "Unrecognised OEM table entry type! - %d\n",
251 static __init void early_check_numaq(
void)
257 early_get_smp_config();
260 x86_init.mpparse.mpc_record = numaq_mpc_record;
262 x86_init.mpparse.mpc_apic_id = mpc_apic_id;
263 x86_init.mpparse.smp_read_mpc_oem = smp_read_mpc_oem;
264 x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus;
265 x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info;
266 x86_init.timers.tsc_pre_init = numaq_tsc_init;
281 #define NUMAQ_APIC_DFR_VALUE (APIC_DFR_CLUSTER)
283 static inline unsigned int numaq_get_apic_id(
unsigned long x)
285 return (x >> 24) & 0x0F;
290 default_send_IPI_mask_sequence_logical(mask, vector);
293 static inline void numaq_send_IPI_allbutself(
int vector)
295 default_send_IPI_mask_allbutself_logical(cpu_online_mask, vector);
298 static inline void numaq_send_IPI_all(
int vector)
300 numaq_send_IPI_mask(cpu_online_mask, vector);
303 #define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8)
304 #define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa)
310 static inline void numaq_smp_callin_clear_local_apic(
void)
315 static inline const struct cpumask *numaq_target_cpus(
void)
325 static inline unsigned long numaq_check_apicid_present(
int bit)
330 static inline int numaq_apic_id_registered(
void)
335 static inline void numaq_init_apic_ldr(
void)
340 static inline void numaq_setup_apic_routing(
void)
343 "Enabling APIC mode: NUMA-Q. Using %d I/O APICs\n",
351 static inline int numaq_multi_timer_check(
int apic,
int irq)
353 return apic != 0 && irq == 0;
359 return physids_promote(0xFUL, retmap);
367 static inline int numaq_cpu_present_to_apicid(
int mps_cpu)
370 return ((mps_cpu >> 2) << 4) | (1 << (mps_cpu & 0x3));
375 static inline int numaq_apicid_to_node(
int logical_apicid)
377 return logical_apicid >> 4;
380 static int numaq_numa_cpu_node(
int cpu)
382 int logical_apicid =
early_per_cpu(x86_cpu_to_logical_apicid, cpu);
385 return numaq_apicid_to_node(logical_apicid);
389 static void numaq_apicid_to_cpu_present(
int logical_apicid,
physid_mask_t *retmap)
391 int node = numaq_apicid_to_node(logical_apicid);
392 int cpu =
__ffs(logical_apicid & 0xf);
394 physid_set_mask_of_physid(cpu + 4*node, retmap);
400 static inline int numaq_check_phys_apicid_present(
int phys_apicid)
411 const struct cpumask *andmask,
419 static inline int numaq_phys_pkg_id(
int cpuid_apic,
int index_msb)
421 return cpuid_apic >> index_msb;
425 numaq_mps_oem_check(
struct mpc_table *mpc,
char *oem,
char *productid)
427 if (
strncmp(oem,
"IBM NUMA", 8))
435 static int probe_numaq(
void)
441 static void numaq_setup_portio_remap(
void)
449 "Remapping cross-quad port I/O for %d quads\n", num_quads);
451 xquad_portio =
ioremap(XQUAD_PORTIO_BASE, num_quads*XQUAD_PORTIO_QUAD);
454 "xquad_portio vaddr 0x%08lx, len %08lx\n",
455 (
u_long) xquad_portio, (
u_long) num_quads*XQUAD_PORTIO_QUAD);
462 .probe = probe_numaq,
463 .acpi_madt_oem_check =
NULL,
464 .apic_id_valid = default_apic_id_valid,
465 .apic_id_registered = numaq_apic_id_registered,
471 .target_cpus = numaq_target_cpus,
474 .check_apicid_used = numaq_check_apicid_used,
475 .check_apicid_present = numaq_check_apicid_present,
477 .vector_allocation_domain = flat_vector_allocation_domain,
478 .init_apic_ldr = numaq_init_apic_ldr,
480 .ioapic_phys_id_map = numaq_ioapic_phys_id_map,
481 .setup_apic_routing = numaq_setup_apic_routing,
482 .multi_timer_check = numaq_multi_timer_check,
483 .cpu_present_to_apicid = numaq_cpu_present_to_apicid,
484 .apicid_to_cpu_present = numaq_apicid_to_cpu_present,
485 .setup_portio_remap = numaq_setup_portio_remap,
486 .check_phys_apicid_present = numaq_check_phys_apicid_present,
487 .enable_apic_mode =
NULL,
488 .phys_pkg_id = numaq_phys_pkg_id,
489 .mps_oem_check = numaq_mps_oem_check,
491 .get_apic_id = numaq_get_apic_id,
493 .apic_id_mask = 0x0F << 24,
495 .cpu_mask_to_apicid_and = numaq_cpu_mask_to_apicid_and,
497 .send_IPI_mask = numaq_send_IPI_mask,
498 .send_IPI_mask_allbutself =
NULL,
499 .send_IPI_allbutself = numaq_send_IPI_allbutself,
500 .send_IPI_all = numaq_send_IPI_all,
501 .send_IPI_self = default_send_IPI_self,
508 .wait_for_init_deassert =
NULL,
510 .smp_callin_clear_local_apic = numaq_smp_callin_clear_local_apic,
511 .inquire_remote_apic =
NULL,
513 .read = native_apic_mem_read,
514 .write = native_apic_mem_write,
515 .eoi_write = native_apic_mem_write,
521 .x86_32_early_logical_apicid = noop_x86_32_early_logical_apicid,
522 .x86_32_numa_cpu_node = numaq_numa_cpu_node,