2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00
linux/arch/s390/kernel/processor.c
Heiko Carstens e76b8c1d7a s390: Simple strcpy() to strscpy() conversions
Convert all strcpy() usages to strscpy() where the conversion means
just replacing strcpy() with strscpy(). strcpy() is deprecated since
it performs no bounds checking on the destination buffer.

Reviewed-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
2025-04-30 11:41:27 +02:00

388 lines
8.9 KiB
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,
};