cregit-Linux how code gets into the kernel

Release 4.14 arch/powerpc/platforms/pseries/smp.c

/*
 * SMP support for pSeries machines.
 *
 * Dave Engebretsen, Peter Bergner, and
 * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
 *
 * Plus various changes from other IBM teams...
 *
 *      This program is free software; you can redistribute it and/or
 *      modify it under the terms of the GNU General Public License
 *      as published by the Free Software Foundation; either version
 *      2 of the License, or (at your option) any later version.
 */


#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/cache.h>
#include <linux/err.h>
#include <linux/device.h>
#include <linux/cpu.h>

#include <asm/ptrace.h>
#include <linux/atomic.h>
#include <asm/irq.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/io.h>
#include <asm/prom.h>
#include <asm/smp.h>
#include <asm/paca.h>
#include <asm/machdep.h>
#include <asm/cputable.h>
#include <asm/firmware.h>
#include <asm/rtas.h>
#include <asm/vdso_datapage.h>
#include <asm/cputhreads.h>
#include <asm/xics.h>
#include <asm/xive.h>
#include <asm/dbell.h>
#include <asm/plpar_wrappers.h>
#include <asm/code-patching.h>

#include "pseries.h"
#include "offline_states.h"


/*
 * The Primary thread of each non-boot processor was started from the OF client
 * interface by prom_hold_cpus and is spinning on secondary_hold_spinloop.
 */

static cpumask_var_t of_spin_mask;

/* Query where a cpu is now.  Return codes #defined in plpar_wrappers.h */

int smp_query_cpu_stopped(unsigned int pcpu) { int cpu_status, status; int qcss_tok = rtas_token("query-cpu-stopped-state"); if (qcss_tok == RTAS_UNKNOWN_SERVICE) { printk_once(KERN_INFO "Firmware doesn't support query-cpu-stopped-state\n"); return QCSS_HARDWARE_ERROR; } status = rtas_call(qcss_tok, 1, 2, &cpu_status, pcpu); if (status != 0) { printk(KERN_ERR "RTAS query-cpu-stopped-state failed: %i\n", status); return status; } return cpu_status; }

Contributors

PersonTokensPropCommitsCommitProp
Michael Neuling7597.40%150.00%
Milton D. Miller II22.60%150.00%
Total77100.00%2100.00%

/** * smp_startup_cpu() - start the given cpu * * At boot time, there is nothing to do for primary threads which were * started from Open Firmware. For anything else, call RTAS with the * appropriate start location. * * Returns: * 0 - failure * 1 - success */
static inline int smp_startup_cpu(unsigned int lcpu) { int status; unsigned long start_here = __pa(ppc_function_entry(generic_secondary_smp_init)); unsigned int pcpu; int start_cpu; if (cpumask_test_cpu(lcpu, of_spin_mask)) /* Already started by OF and sitting in spin loop */ return 1; pcpu = get_hard_smp_processor_id(lcpu); /* Check to see if the CPU out of FW already for kexec */ if (smp_query_cpu_stopped(pcpu) == QCSS_NOT_STOPPED){ cpumask_set_cpu(lcpu, of_spin_mask); return 1; } /* Fixup atomic count: it exited inside IRQ handler. */ task_thread_info(paca[lcpu].__current)->preempt_count = 0; #ifdef CONFIG_HOTPLUG_CPU if (get_cpu_current_state(lcpu) == CPU_STATE_INACTIVE) goto out; #endif /* * If the RTAS start-cpu token does not exist then presume the * cpu is already spinning. */ start_cpu = rtas_token("start-cpu"); if (start_cpu == RTAS_UNKNOWN_SERVICE) return 1; status = rtas_call(start_cpu, 3, 1, NULL, pcpu, start_here, pcpu); if (status != 0) { printk(KERN_ERR "start-cpu failed: %i\n", status); return 0; } #ifdef CONFIG_HOTPLUG_CPU out: #endif return 1; }

Contributors

PersonTokensPropCommitsCommitProp
Paul Mackerras8247.67%19.09%
Anton Blanchard2715.70%327.27%
Michael Neuling2011.63%19.09%
Benjamin Herrenschmidt148.14%19.09%
Gautham R. Shenoy148.14%19.09%
Matt Evans105.81%19.09%
Al Viro31.74%19.09%
Michael Ellerman10.58%19.09%
Olof Johansson10.58%19.09%
Total172100.00%11100.00%


static void smp_setup_cpu(int cpu) { if (xive_enabled()) xive_smp_setup_cpu(); else if (cpu != boot_cpuid) xics_setup_cpu(); if (firmware_has_feature(FW_FEATURE_SPLPAR)) vpa_init(cpu); cpumask_clear_cpu(cpu, of_spin_mask); #ifdef CONFIG_HOTPLUG_CPU set_cpu_current_state(cpu, CPU_STATE_ONLINE); set_default_offline_state(cpu); #endif }

Contributors

PersonTokensPropCommitsCommitProp
Benjamin Herrenschmidt1726.98%111.11%
Gautham R. Shenoy1219.05%111.11%
Anton Blanchard1117.46%222.22%
Cédric Le Goater914.29%111.11%
Paul Mackerras57.94%111.11%
Matt Evans57.94%111.11%
Stephen Rothwell34.76%111.11%
Rashmica Gupta11.59%111.11%
Total63100.00%9100.00%


static int smp_pSeries_kick_cpu(int nr) { if (nr < 0 || nr >= nr_cpu_ids) return -EINVAL; if (!smp_startup_cpu(nr)) return -ENOENT; /* * The processor is currently spinning, waiting for the * cpu_start field to become non-zero After we set cpu_start, * the processor will continue on to secondary_start */ paca[nr].cpu_start = 1; #ifdef CONFIG_HOTPLUG_CPU set_preferred_offline_state(nr, CPU_STATE_ONLINE); if (get_cpu_current_state(nr) == CPU_STATE_INACTIVE) { long rc; unsigned long hcpuid; hcpuid = get_hard_smp_processor_id(nr); rc = plpar_hcall_norets(H_PROD, hcpuid); if (rc != H_SUCCESS) printk(KERN_ERR "Error: Prod to wake up processor %d " "Ret= %ld\n", nr, rc); } #endif return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Gautham R. Shenoy4944.14%222.22%
Benjamin Herrenschmidt3127.93%111.11%
Matt Evans1210.81%111.11%
Michael Ellerman87.21%111.11%
Santosh Sivaraj87.21%222.22%
Joe Perches21.80%111.11%
Anton Blanchard10.90%111.11%
Total111100.00%9100.00%


static int pseries_smp_prepare_cpu(int cpu) { if (xive_enabled()) return xive_smp_prepare_cpu(cpu); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Cédric Le Goater23100.00%1100.00%
Total23100.00%1100.00%


static void smp_pseries_cause_ipi(int cpu) { /* POWER9 should not use this handler */ if (doorbell_try_core_ipi(cpu)) return; icp_ops->cause_ipi(cpu); }

Contributors

PersonTokensPropCommitsCommitProp
Ian Munsie1872.00%150.00%
Nicholas Piggin728.00%150.00%
Total25100.00%2100.00%


static int pseries_cause_nmi_ipi(int cpu) { int hwcpu; if (cpu == NMI_IPI_ALL_OTHERS) { hwcpu = H_SIGNAL_SYS_RESET_ALL_OTHERS; } else { if (cpu < 0) { WARN_ONCE(true, "incorrect cpu parameter %d", cpu); return 0; } hwcpu = get_hard_smp_processor_id(cpu); } if (plapr_signal_sys_reset(hwcpu) == H_SUCCESS) return 1; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Nicholas Piggin69100.00%1100.00%
Total69100.00%1100.00%


static __init void pSeries_smp_probe_xics(void) { xics_smp_probe(); if (cpu_has_feature(CPU_FTR_DBELL)) smp_ops->cause_ipi = smp_pseries_cause_ipi; else smp_ops->cause_ipi = icp_ops->cause_ipi; }

Contributors

PersonTokensPropCommitsCommitProp
Ian Munsie2573.53%125.00%
Nicholas Piggin617.65%125.00%
Michael Ellerman25.88%125.00%
Cédric Le Goater12.94%125.00%
Total34100.00%4100.00%


static __init void pSeries_smp_probe(void) { if (xive_enabled()) /* * Don't use P9 doorbells when XIVE is enabled. IPIs * using MMIOs should be faster */ xive_smp_probe(); else pSeries_smp_probe_xics(); }

Contributors

PersonTokensPropCommitsCommitProp
Cédric Le Goater22100.00%1100.00%
Total22100.00%1100.00%

static struct smp_ops_t pseries_smp_ops = { .message_pass = NULL, /* Use smp_muxed_ipi_message_pass */ .cause_ipi = NULL, /* Filled at runtime by pSeries_smp_probe() */ .cause_nmi_ipi = pseries_cause_nmi_ipi, .probe = pSeries_smp_probe, .prepare_cpu = pseries_smp_prepare_cpu, .kick_cpu = smp_pSeries_kick_cpu, .setup_cpu = smp_setup_cpu, .cpu_bootable = smp_generic_cpu_bootable, }; /* This is called very early */
void __init smp_init_pseries(void) { int i; pr_debug(" -> smp_init_pSeries()\n"); smp_ops = &pseries_smp_ops; alloc_bootmem_cpumask_var(&of_spin_mask); /* * Mark threads which are still spinning in hold loops * * We know prom_init will not have started them if RTAS supports * query-cpu-stopped-state. */ if (rtas_token("query-cpu-stopped-state") == RTAS_UNKNOWN_SERVICE) { if (cpu_has_feature(CPU_FTR_SMT)) { for_each_present_cpu(i) { if (cpu_thread_in_core(i) == 0) cpumask_set_cpu(i, of_spin_mask); } } else cpumask_copy(of_spin_mask, cpu_present_mask); cpumask_clear_cpu(boot_cpuid, of_spin_mask); } /* Non-lpar has additional take/give timebase */ if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { smp_ops->give_timebase = rtas_give_timebase; smp_ops->take_timebase = rtas_take_timebase; } pr_debug(" <- smp_init_pSeries()\n"); }

Contributors

PersonTokensPropCommitsCommitProp
Benjamin Herrenschmidt6960.53%436.36%
Anton Blanchard2723.68%327.27%
Paul Mackerras87.02%19.09%
Rashmica Gupta54.39%19.09%
Milton D. Miller II32.63%19.09%
Michael Ellerman21.75%19.09%
Total114100.00%11100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Benjamin Herrenschmidt23326.87%613.04%
Paul Mackerras10812.46%510.87%
Michael Neuling9611.07%24.35%
Nicholas Piggin8710.03%36.52%
Gautham R. Shenoy789.00%24.35%
Anton Blanchard718.19%613.04%
Cédric Le Goater637.27%12.17%
Ian Munsie485.54%12.17%
Matt Evans273.11%12.17%
Michael Ellerman131.50%48.70%
Milton D. Miller II121.38%48.70%
Rashmica Gupta80.92%12.17%
Santosh Sivaraj80.92%24.35%
Stephen Rothwell50.58%12.17%
Al Viro30.35%12.17%
Joe Perches20.23%12.17%
Kay Sievers10.12%12.17%
Arun Sharma10.12%12.17%
Olof Johansson10.12%12.17%
Deepthi Dharwar10.12%12.17%
Andy Fleming10.12%12.17%
Total867100.00%46100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.