Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/arch/s390/kernel/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 8 kB image not shown  

Quelle  processor.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 *  Copyright IBM Corp. 2008
 *  Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
 */


#define KMSG_COMPONENT "cpu"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

#include <linux/stop_machine.h>
#include <linux/cpufeature.h>
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/random.h>
#include <linux/sched/mm.h>
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/mm_types.h>
#include <linux/delay.h>
#include <linux/cpu.h>
#include <linux/smp.h>
#include <asm/text-patching.h>
#include <asm/machine.h>
#include <asm/diag.h>
#include <asm/facility.h>
#include <asm/elf.h>
#include <asm/lowcore.h>
#include <asm/param.h>
#include <asm/sclp.h>
#include <asm/smp.h>

unsigned long __read_mostly elf_hwcap;
char elf_platform[ELF_PLATFORM_SIZE];

struct cpu_info {
 unsigned int cpu_mhz_dynamic;
 unsigned int cpu_mhz_static;
 struct cpuid cpu_id;
};

static DEFINE_PER_CPU(struct cpu_info, cpu_info);
static DEFINE_PER_CPU(int, cpu_relax_retry);

static bool machine_has_cpu_mhz;

void __init cpu_detect_mhz_feature(void)
{
 if (test_facility(34) && __ecag(ECAG_CPU_ATTRIBUTE, 0) != -1UL)
  machine_has_cpu_mhz = true;
}

static void update_cpu_mhz(void *arg)
{
 unsigned long mhz;
 struct cpu_info *c;

 mhz = __ecag(ECAG_CPU_ATTRIBUTE, 0);
 c = this_cpu_ptr(&cpu_info);
 c->cpu_mhz_dynamic = mhz >> 32;
 c->cpu_mhz_static = mhz & 0xffffffff;
}

void s390_update_cpu_mhz(void)
{
 s390_adjust_jiffies();
 if (machine_has_cpu_mhz)
  on_each_cpu(update_cpu_mhz, NULL, 0);
}

void notrace stop_machine_yield(const struct cpumask *cpumask)
{
 int cpu, this_cpu;

 this_cpu = smp_processor_id();
 if (__this_cpu_inc_return(cpu_relax_retry) >= spin_retry) {
  __this_cpu_write(cpu_relax_retry, 0);
  cpu = cpumask_next_wrap(this_cpu, cpumask);
  if (cpu >= nr_cpu_ids)
   return;
  if (arch_vcpu_is_preempted(cpu))
   smp_yield_cpu(cpu);
 }
}

static void do_sync_core(void *info)
{
 sync_core();
}

void text_poke_sync(void)
{
 on_each_cpu(do_sync_core, NULL, 1);
}

void text_poke_sync_lock(void)
{
 cpus_read_lock();
 text_poke_sync();
 cpus_read_unlock();
}

/*
 * cpu_init - initializes state that is per-CPU.
 */

void cpu_init(void)
{
 struct cpuid *id = this_cpu_ptr(&cpu_info.cpu_id);

 get_cpu_id(id);
 if (machine_has_cpu_mhz)
  update_cpu_mhz(NULL);
 mmgrab(&init_mm);
 current->active_mm = &init_mm;
 BUG_ON(current->mm);
 enter_lazy_tlb(&init_mm, current);
}

static void show_facilities(struct seq_file *m)
{
 unsigned int bit;

 seq_puts(m, "facilities :");
 for_each_set_bit_inv(bit, (long *)&stfle_fac_list, MAX_FACILITY_BIT)
  seq_printf(m, " %d", bit);
 seq_putc(m, '\n');
}

static void show_cpu_summary(struct seq_file *m, void *v)
{
 static const char *hwcap_str[] = {
  [HWCAP_NR_ESAN3] = "esan3",
  [HWCAP_NR_ZARCH] = "zarch",
  [HWCAP_NR_STFLE] = "stfle",
  [HWCAP_NR_MSA]  = "msa",
  [HWCAP_NR_LDISP] = "ldisp",
  [HWCAP_NR_EIMM]  = "eimm",
  [HWCAP_NR_DFP]  = "dfp",
  [HWCAP_NR_HPAGE] = "edat",
  [HWCAP_NR_ETF3EH] = "etf3eh",
  [HWCAP_NR_HIGH_GPRS] = "highgprs",
  [HWCAP_NR_TE]  = "te",
  [HWCAP_NR_VXRS]  = "vx",
  [HWCAP_NR_VXRS_BCD] = "vxd",
  [HWCAP_NR_VXRS_EXT] = "vxe",
  [HWCAP_NR_GS]  = "gs",
  [HWCAP_NR_VXRS_EXT2] = "vxe2",
  [HWCAP_NR_VXRS_PDE] = "vxp",
  [HWCAP_NR_SORT]  = "sort",
  [HWCAP_NR_DFLT]  = "dflt",
  [HWCAP_NR_VXRS_PDE2] = "vxp2",
  [HWCAP_NR_NNPA]  = "nnpa",
  [HWCAP_NR_PCI_MIO] = "pcimio",
  [HWCAP_NR_SIE]  = "sie",
 };
 int i, cpu;

 BUILD_BUG_ON(ARRAY_SIZE(hwcap_str) != HWCAP_NR_MAX);
 seq_printf(m, "vendor_id : IBM/S390\n"
     "# processors : %i\n"
     "bogomips per cpu: %lu.%02lu\n",
     num_online_cpus(), loops_per_jiffy/(500000/HZ),
     (loops_per_jiffy/(5000/HZ))%100);
 seq_printf(m, "max thread id : %d\n", smp_cpu_mtid);
 seq_puts(m, "features\t: ");
 for (i = 0; i < ARRAY_SIZE(hwcap_str); i++)
  if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
   seq_printf(m, "%s ", hwcap_str[i]);
 seq_puts(m, "\n");
 show_facilities(m);
 show_cacheinfo(m);
 for_each_online_cpu(cpu) {
  struct cpuid *id = &per_cpu(cpu_info.cpu_id, cpu);

  seq_printf(m, "processor %d: "
      "version = %02X, "
      "identification = %06X, "
      "machine = %04X\n",
      cpu, id->version, id->ident, id->machine);
 }
}

static int __init setup_hwcaps(void)
{
 /* instructions named N3, "backported" to esa-mode */
 elf_hwcap |= HWCAP_ESAN3;

 /* z/Architecture mode active */
 elf_hwcap |= HWCAP_ZARCH;

 /* store-facility-list-extended */
 if (test_facility(7))
  elf_hwcap |= HWCAP_STFLE;

 /* message-security assist */
 if (test_facility(17))
  elf_hwcap |= HWCAP_MSA;

 /* long-displacement */
 if (test_facility(19))
  elf_hwcap |= HWCAP_LDISP;

 /* extended-immediate */
 elf_hwcap |= HWCAP_EIMM;

 /* extended-translation facility 3 enhancement */
 if (test_facility(22) && test_facility(30))
  elf_hwcap |= HWCAP_ETF3EH;

 /* decimal floating point & perform floating point operation */
 if (test_facility(42) && test_facility(44))
  elf_hwcap |= HWCAP_DFP;

 /* huge page support */
 if (cpu_has_edat1())
  elf_hwcap |= HWCAP_HPAGE;

 /* 64-bit register support for 31-bit processes */
 elf_hwcap |= HWCAP_HIGH_GPRS;

 /* transactional execution */
 if (machine_has_tx())
  elf_hwcap |= HWCAP_TE;

 /* vector */
 if (test_facility(129)) {
  elf_hwcap |= HWCAP_VXRS;
  if (test_facility(134))
   elf_hwcap |= HWCAP_VXRS_BCD;
  if (test_facility(135))
   elf_hwcap |= HWCAP_VXRS_EXT;
  if (test_facility(148))
   elf_hwcap |= HWCAP_VXRS_EXT2;
  if (test_facility(152))
   elf_hwcap |= HWCAP_VXRS_PDE;
  if (test_facility(192))
   elf_hwcap |= HWCAP_VXRS_PDE2;
 }

 if (test_facility(150))
  elf_hwcap |= HWCAP_SORT;

 if (test_facility(151))
  elf_hwcap |= HWCAP_DFLT;

 if (test_facility(165))
  elf_hwcap |= HWCAP_NNPA;

 /* guarded storage */
 if (cpu_has_gs())
  elf_hwcap |= HWCAP_GS;

 if (test_machine_feature(MFEATURE_PCI_MIO))
  elf_hwcap |= HWCAP_PCI_MIO;

 /* virtualization support */
 if (sclp.has_sief2)
  elf_hwcap |= HWCAP_SIE;

 return 0;
}
arch_initcall(setup_hwcaps);

static int __init setup_elf_platform(void)
{
 struct cpuid cpu_id;

 get_cpu_id(&cpu_id);
 add_device_randomness(&cpu_id, sizeof(cpu_id));
 switch (cpu_id.machine) {
 default/* Use "z10" as default. */
  strscpy(elf_platform, "z10");
  break;
 case 0x2817:
 case 0x2818:
  strscpy(elf_platform, "z196");
  break;
 case 0x2827:
 case 0x2828:
  strscpy(elf_platform, "zEC12");
  break;
 case 0x2964:
 case 0x2965:
  strscpy(elf_platform, "z13");
  break;
 case 0x3906:
 case 0x3907:
  strscpy(elf_platform, "z14");
  break;
 case 0x8561:
 case 0x8562:
  strscpy(elf_platform, "z15");
  break;
 case 0x3931:
 case 0x3932:
  strscpy(elf_platform, "z16");
  break;
 case 0x9175:
 case 0x9176:
  strscpy(elf_platform, "z17");
  break;
 }
 return 0;
}
arch_initcall(setup_elf_platform);

static void show_cpu_topology(struct seq_file *m, unsigned long n)
{
#ifdef CONFIG_SCHED_TOPOLOGY
 seq_printf(m, "physical id : %d\n", topology_physical_package_id(n));
 seq_printf(m, "core id : %d\n", topology_core_id(n));
 seq_printf(m, "book id : %d\n", topology_book_id(n));
 seq_printf(m, "drawer id : %d\n", topology_drawer_id(n));
 seq_printf(m, "dedicated : %d\n", topology_cpu_dedicated(n));
 seq_printf(m, "address : %d\n", smp_cpu_get_cpu_address(n));
 seq_printf(m, "siblings : %d\n", cpumask_weight(topology_core_cpumask(n)));
 seq_printf(m, "cpu cores : %d\n", topology_booted_cores(n));
#endif /* CONFIG_SCHED_TOPOLOGY */
}

static void show_cpu_ids(struct seq_file *m, unsigned long n)
{
 struct cpuid *id = &per_cpu(cpu_info.cpu_id, n);

 seq_printf(m, "version : %02X\n", id->version);
 seq_printf(m, "identification : %06X\n", id->ident);
 seq_printf(m, "machine : %04X\n", id->machine);
}

static void show_cpu_mhz(struct seq_file *m, unsigned long n)
{
 struct cpu_info *c = per_cpu_ptr(&cpu_info, n);

 if (!machine_has_cpu_mhz)
  return;
 seq_printf(m, "cpu MHz dynamic : %d\n", c->cpu_mhz_dynamic);
 seq_printf(m, "cpu MHz static : %d\n", c->cpu_mhz_static);
}

/*
 * show_cpuinfo - Get information on one CPU for use by procfs.
 */

static int show_cpuinfo(struct seq_file *m, void *v)
{
 unsigned long n = (unsigned long) v - 1;
 unsigned long first = cpumask_first(cpu_online_mask);

 if (n == first)
  show_cpu_summary(m, v);
 seq_printf(m, "\ncpu number : %ld\n", n);
 show_cpu_topology(m, n);
 show_cpu_ids(m, n);
 show_cpu_mhz(m, n);
 return 0;
}

static inline void *c_update(loff_t *pos)
{
 if (*pos)
  *pos = cpumask_next(*pos - 1, cpu_online_mask);
 else
  *pos = cpumask_first(cpu_online_mask);
 return *pos < nr_cpu_ids ? (void *)*pos + 1 : NULL;
}

static void *c_start(struct seq_file *m, loff_t *pos)
{
 cpus_read_lock();
 return c_update(pos);
}

static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
 ++*pos;
 return c_update(pos);
}

static void c_stop(struct seq_file *m, void *v)
{
 cpus_read_unlock();
}

const struct seq_operations cpuinfo_op = {
 .start = c_start,
 .next = c_next,
 .stop = c_stop,
 .show = show_cpuinfo,
};

Messung V0.5
C=95 H=89 G=91

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.