static void common_shutdown_1(void *generic_ptr) { struct halt_info *how = (struct halt_info *)generic_ptr; struct percpu_struct *cpup; unsigned long *pflags, flags; int cpuid = smp_processor_id(); /* No point in taking interrupts anymore. */ local_irq_disable(); cpup = (struct percpu_struct *) ((unsigned long)hwrpb + hwrpb->processor_offset + hwrpb->processor_size * cpuid); pflags = &cpup->flags; flags = *pflags; /* Clear reason to "default"; clear "bootstrap in progress". */ flags &= ~0x00ff0001UL; #ifdef CONFIG_SMP /* Secondaries halt here. */ if (cpuid != boot_cpuid) { flags |= 0x00040000UL; /* "remain halted" */ *pflags = flags; set_cpu_present(cpuid, false); set_cpu_possible(cpuid, false); halt(); } #endif if (how->mode == LINUX_REBOOT_CMD_RESTART) { if (!how->restart_cmd) { flags |= 0x00020000UL; /* "cold bootstrap" */ } else { /* For SRM, we could probably set environment variables to get this to work. We'd have to delay this until after srm_paging_stop unless we ever got srm_fixup working. At the moment, SRM will use the last boot device, but the file and flags will be the defaults, when doing a "warm" bootstrap. */ flags |= 0x00030000UL; /* "warm bootstrap" */ } } else { flags |= 0x00040000UL; /* "remain halted" */ } *pflags = flags; #ifdef CONFIG_SMP /* Wait for the secondaries to halt. */ set_cpu_present(boot_cpuid, false); set_cpu_possible(boot_cpuid, false); while (cpus_weight(cpu_present_map)) barrier(); #endif /* If booted from SRM, reset some of the original environment. */ if (alpha_using_srm) { #ifdef CONFIG_DUMMY_CONSOLE /* If we've gotten here after SysRq-b, leave interrupt context before taking over the console. */ if (in_interrupt()) irq_exit(); /* This has the effect of resetting the VGA video origin. */ take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1); #endif pci_restore_srm_config(); set_hae(srm_hae); } if (alpha_mv.kill_arch) alpha_mv.kill_arch(how->mode); if (! alpha_using_srm && how->mode != LINUX_REBOOT_CMD_RESTART) { /* Unfortunately, since MILO doesn't currently understand the hwrpb bits above, we can't reliably halt the processor and keep it halted. So just loop. */ return; } if (alpha_using_srm) srm_paging_stop(); halt(); }
static int __init smp_iic_probe(void) { iic_request_IPIs(); return cpus_weight(cpu_possible_map); }
/* * Display cpu info for all cpu's. */ static int show_cpuinfo (struct seq_file *m, void *v) { #ifdef CONFIG_SMP # define lpj c->loops_per_jiffy # define cpunum c->cpu #else # define lpj loops_per_jiffy # define cpunum 0 #endif static struct { unsigned long mask; const char *feature_name; } feature_bits[] = { { 1UL << 0, "branchlong" }, { 1UL << 1, "spontaneous deferral"}, { 1UL << 2, "16-byte atomic ops" } }; char family[32], features[128], *cp, sep; struct cpuinfo_ia64 *c = v; unsigned long mask; unsigned long proc_freq; int i; mask = c->features; switch (c->family) { case 0x07: memcpy(family, "Itanium", 8); break; case 0x1f: memcpy(family, "Itanium 2", 10); break; default: sprintf(family, "%u", c->family); break; } /* build the feature string: */ memcpy(features, " standard", 10); cp = features; sep = 0; for (i = 0; i < (int) ARRAY_SIZE(feature_bits); ++i) { if (mask & feature_bits[i].mask) { if (sep) *cp++ = sep; sep = ','; *cp++ = ' '; strcpy(cp, feature_bits[i].feature_name); cp += strlen(feature_bits[i].feature_name); mask &= ~feature_bits[i].mask; } } if (mask) { /* print unknown features as a hex value: */ if (sep) *cp++ = sep; sprintf(cp, " 0x%lx", mask); } proc_freq = cpufreq_quick_get(cpunum); if (!proc_freq) proc_freq = c->proc_freq / 1000; seq_printf(m, "processor : %d\n" "vendor : %s\n" "arch : IA-64\n" "family : %s\n" "model : %u\n" "revision : %u\n" "archrev : %u\n" "features :%s\n" /* don't change this---it _is_ right! */ "cpu number : %lu\n" "cpu regs : %u\n" "cpu MHz : %lu.%06lu\n" "itc MHz : %lu.%06lu\n" "BogoMIPS : %lu.%02lu\n", cpunum, c->vendor, family, c->model, c->revision, c->archrev, features, c->ppn, c->number, proc_freq / 1000, proc_freq % 1000, c->itc_freq / 1000000, c->itc_freq % 1000000, lpj*HZ/500000, (lpj*HZ/5000) % 100); #ifdef CONFIG_SMP seq_printf(m, "siblings : %u\n", cpus_weight(cpu_core_map[cpunum])); if (c->threads_per_core > 1 || c->cores_per_socket > 1) seq_printf(m, "physical id: %u\n" "core id : %u\n" "thread id : %u\n", c->socket_id, c->core_id, c->thread_id); #endif seq_printf(m,"\n"); return 0; }
static int __init smp_a2_probe(void) { return cpus_weight(cpu_possible_map); }
/* * These functions send a 'generic call function' IPI to other online * CPUS in the system. * * [SUMMARY] Run a function on other CPUs. * <func> The function to run. This must be fast and non-blocking. * <info> An arbitrary pointer to pass to the function. * <nonatomic> currently unused. * <wait> If true, wait (atomically) until function has completed on other CPUs. * [RETURNS] 0 on success, else a negative status code. Does not return until * remote CPUs are nearly ready to execute <<func>> or are or have executed. * <map> is a cpu map of the cpus to send IPI to. * * You must not call this function with disabled interrupts or from a * hardware interrupt handler or from a bottom half handler. */ static int __smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, int wait, cpumask_t map) { struct call_data_struct data; int ret = -1, num_cpus; int cpu; u64 timeout; if (unlikely(smp_ops == NULL)) return ret; data.func = func; data.info = info; atomic_set(&data.started, 0); data.wait = wait; if (wait) atomic_set(&data.finished, 0); /* remove 'self' from the map */ if (cpu_isset(smp_processor_id(), map)) cpu_clear(smp_processor_id(), map); /* sanity check the map, remove any non-online processors. */ cpus_and(map, map, cpu_online_map); num_cpus = cpus_weight(map); if (!num_cpus) goto done; call_data = &data; smp_wmb(); /* Send a message to all CPUs in the map */ for_each_cpu_mask(cpu, map) smp_ops->message_pass(cpu, PPC_MSG_CALL_FUNCTION); timeout = get_tb() + (u64) SMP_CALL_TIMEOUT * tb_ticks_per_sec; /* Wait for indication that they have received the message */ while (atomic_read(&data.started) != num_cpus) { HMT_low(); if (get_tb() >= timeout) { printk("smp_call_function on cpu %d: other cpus not " "responding (%d)\n", smp_processor_id(), atomic_read(&data.started)); if (!ipi_fail_ok) debugger(NULL); goto out; } } /* optionally wait for the CPUs to complete */ if (wait) { while (atomic_read(&data.finished) != num_cpus) { HMT_low(); if (get_tb() >= timeout) { printk("smp_call_function on cpu %d: other " "cpus not finishing (%d/%d)\n", smp_processor_id(), atomic_read(&data.finished), atomic_read(&data.started)); debugger(NULL); goto out; } } } done: ret = 0; out: call_data = NULL; HMT_medium(); return ret; }
/* * Display cpu info for all cpu's. */ static int show_cpuinfo (struct seq_file *m, void *v) { #ifdef CONFIG_SMP # define lpj c->loops_per_jiffy # define cpunum c->cpu #else # define lpj loops_per_jiffy # define cpunum 0 #endif static struct { unsigned long mask; const char *feature_name; } feature_bits[] = { { 1UL << 0, "branchlong" }, { 1UL << 1, "spontaneous deferral"}, { 1UL << 2, "16-byte atomic ops" } }; char features[128], *cp, *sep; struct cpuinfo_ia64 *c = v; unsigned long mask; unsigned long proc_freq; int i, size; mask = c->features; /* build the feature string: */ memcpy(features, "standard", 9); cp = features; size = sizeof(features); sep = ""; for (i = 0; i < ARRAY_SIZE(feature_bits) && size > 1; ++i) { if (mask & feature_bits[i].mask) { cp += snprintf(cp, size, "%s%s", sep, feature_bits[i].feature_name), sep = ", "; mask &= ~feature_bits[i].mask; size = sizeof(features) - (cp - features); } } if (mask && size > 1) { /* print unknown features as a hex value */ snprintf(cp, size, "%s0x%lx", sep, mask); } proc_freq = cpufreq_quick_get(cpunum); if (!proc_freq) proc_freq = c->proc_freq / 1000; seq_printf(m, "processor : %d\n" "vendor : %s\n" "arch : IA-64\n" "family : %u\n" "model : %u\n" "model name : %s\n" "revision : %u\n" "archrev : %u\n" "features : %s\n" "cpu number : %lu\n" "cpu regs : %u\n" "cpu MHz : %lu.%03lu\n" "itc MHz : %lu.%06lu\n" "BogoMIPS : %lu.%02lu\n", cpunum, c->vendor, c->family, c->model, c->model_name, c->revision, c->archrev, features, c->ppn, c->number, proc_freq / 1000, proc_freq % 1000, c->itc_freq / 1000000, c->itc_freq % 1000000, lpj*HZ/500000, (lpj*HZ/5000) % 100); #ifdef CONFIG_SMP seq_printf(m, "siblings : %u\n", cpus_weight(cpu_core_map[cpunum])); if (c->threads_per_core > 1 || c->cores_per_socket > 1) seq_printf(m, "physical id: %u\n" "core id : %u\n" "thread id : %u\n", c->socket_id, c->core_id, c->thread_id); #endif seq_printf(m,"\n"); return 0; }
/* * Get CPU information for use by the procfs. */ static int show_cpuinfo(struct seq_file *m, void *v) { /* * These flag bits must match the definitions in <asm/cpufeature.h>. * NULL means this bit is undefined or reserved; either way it doesn't * have meaning as far as Linux is concerned. Note that it's important * to realize there is a difference between this table and CPUID -- if * applications want to get the raw CPUID data, they should access * /dev/cpu/<cpu_nr>/cpuid instead. */ static const char * const x86_cap_flags[] = { /* Intel-defined */ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe", /* AMD-defined */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "mp", "nx", NULL, "mmxext", NULL, NULL, "fxsr_opt", "pdpe1gb", "rdtscp", NULL, "lm", "3dnowext", "3dnow", /* Transmeta-defined */ "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Other (Linux-defined) */ "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", NULL, NULL, NULL, NULL, "constant_tsc", "up", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Intel-defined (#2) */ "pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est", "tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL, NULL, NULL, "dca", NULL, NULL, NULL, NULL, "popcnt", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* VIA/Cyrix/Centaur-defined */ NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en", "ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* AMD-defined (#2) */ "lahf_lm", "cmp_legacy", "svm", "extapic", "cr8legacy", "abm", "sse4a", "misalignsse", "3dnowprefetch", "osvw", "ibs", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; static const char * const x86_power_flags[] = { "ts", /* temperature sensor */ "fid", /* frequency id control */ "vid", /* voltage id control */ "ttp", /* thermal trip */ "tm", "stc", "100mhzsteps", "hwpstate", NULL, NULL, /* constant_tsc - moved to flags */ /* nothing */ }; struct cpuinfo_x86 *c = v; int i, n = c - cpu_data; int fpu_exception; #ifdef CONFIG_SMP if (!cpu_online(n)) return 0; #endif seq_printf(m, "processor\t: %d\n" "vendor_id\t: %s\n" "cpu family\t: %d\n" "model\t\t: %d\n" "model name\t: %s\n", n, c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown", c->x86, c->x86_model, c->x86_model_id[0] ? c->x86_model_id : "unknown"); if (c->x86_mask || c->cpuid_level >= 0) seq_printf(m, "stepping\t: %d\n", c->x86_mask); else seq_printf(m, "stepping\t: unknown\n"); if ( cpu_has(c, X86_FEATURE_TSC) ) { unsigned int freq = cpufreq_quick_get(n); if (!freq) freq = cpu_khz; seq_printf(m, "cpu MHz\t\t: %u.%03u\n", freq / 1000, (freq % 1000)); } /* Cache size */ if (c->x86_cache_size >= 0) seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); #ifdef CONFIG_X86_HT if (c->x86_max_cores * smp_num_siblings > 1) { seq_printf(m, "physical id\t: %d\n", c->phys_proc_id); seq_printf(m, "siblings\t: %d\n", cpus_weight(cpu_core_map[n])); seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id); seq_printf(m, "cpu cores\t: %d\n", c->booted_cores); } #endif /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */ fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu); seq_printf(m, "fdiv_bug\t: %s\n" "hlt_bug\t\t: %s\n" "f00f_bug\t: %s\n" "coma_bug\t: %s\n" "fpu\t\t: %s\n" "fpu_exception\t: %s\n" "cpuid level\t: %d\n" "wp\t\t: %s\n" "flags\t\t:", c->fdiv_bug ? "yes" : "no", c->hlt_works_ok ? "no" : "yes", c->f00f_bug ? "yes" : "no", c->coma_bug ? "yes" : "no", c->hard_math ? "yes" : "no", fpu_exception ? "yes" : "no", c->cpuid_level, c->wp_works_ok ? "yes" : "no"); for ( i = 0 ; i < 32*NCAPINTS ; i++ ) if ( test_bit(i, c->x86_capability) && x86_cap_flags[i] != NULL ) seq_printf(m, " %s", x86_cap_flags[i]); for (i = 0; i < 32; i++) if (c->x86_power & (1 << i)) { if (i < ARRAY_SIZE(x86_power_flags) && x86_power_flags[i]) seq_printf(m, "%s%s", x86_power_flags[i][0]?" ":"", x86_power_flags[i]); else seq_printf(m, " [%d]", i); } seq_printf(m, "\nbogomips\t: %lu.%02lu\n", c->loops_per_jiffy/(500000/HZ), (c->loops_per_jiffy/(5000/HZ)) % 100); seq_printf(m, "clflush size\t: %u\n\n", c->x86_clflush_size); return 0; }
static int __init smp_xen_probe(void) { return cpus_weight(cpu_present_map); }
static int smp_iSeries_probe(void) { return cpus_weight(cpu_possible_map); }