arch/powerpc/platforms/powernv/smp.c

Source file repositories/reference/linux-study-clean/arch/powerpc/platforms/powernv/smp.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/platforms/powernv/smp.c
Extension
.c
Size
10782 bytes
Lines
445
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (rc != OPAL_SUCCESS) {
			pr_warn("OPAL Error %ld starting CPU %d\n", rc, nr);
			return -ENODEV;
		}
	} else {
		/*
		 * An unavailable CPU (or any other unknown status)
		 * shouldn't be started. It should also
		 * not be in the possible map but currently it can
		 * happen
		 */
		pr_devel("OPAL: CPU %d (HW 0x%x) is unavailable"
			 " (status %d)...\n", nr, pcpu, status);
		return -ENODEV;
	}

kick:
	return smp_generic_kick_cpu(nr);
}

#ifdef CONFIG_HOTPLUG_CPU

static int pnv_smp_cpu_disable(void)
{
	int cpu = smp_processor_id();

	/* This is identical to pSeries... might consolidate by
	 * moving migrate_irqs_away to a ppc_md with default to
	 * the generic fixup_irqs. --BenH.
	 */
	set_cpu_online(cpu, false);
#ifdef CONFIG_PPC64_PROC_SYSTEMCFG
	systemcfg->processorCount--;
#endif
	if (cpu == boot_cpuid)
		boot_cpuid = cpumask_any(cpu_online_mask);
	if (xive_enabled())
		xive_smp_disable_cpu();
	else
		xics_migrate_irqs_away();

	cleanup_cpu_mmu_context();

	return 0;
}

static void pnv_flush_interrupts(void)
{
	if (cpu_has_feature(CPU_FTR_ARCH_300)) {
		if (xive_enabled())
			xive_flush_interrupt();
		else
			icp_opal_flush_interrupt();
	} else {
		icp_native_flush_interrupt();
	}
}

static void pnv_cpu_offline_self(void)
{
	unsigned long srr1, unexpected_mask, wmask;
	unsigned int cpu;
	u64 lpcr_val;

	/* Standard hot unplug procedure */

	idle_task_exit();
	cpu = smp_processor_id();
	DBG("CPU%d offline\n", cpu);
	generic_set_cpu_dead(cpu);
	smp_wmb();

	wmask = SRR1_WAKEMASK;
	if (cpu_has_feature(CPU_FTR_ARCH_207S))
		wmask = SRR1_WAKEMASK_P8;

	/*
	 * This turns the irq soft-disabled state we're called with, into a
	 * hard-disabled state with pending irq_happened interrupts cleared.
	 *
	 * PACA_IRQ_DEC   - Decrementer should be ignored.
	 * PACA_IRQ_HMI   - Can be ignored, processing is done in real mode.
	 * PACA_IRQ_DBELL, EE, PMI - Unexpected.
	 */
	hard_irq_disable();
	if (generic_check_cpu_restart(cpu))
		goto out;

	unexpected_mask = ~(PACA_IRQ_DEC | PACA_IRQ_HMI | PACA_IRQ_HARD_DIS);
	if (local_paca->irq_happened & unexpected_mask) {

Annotation

Implementation Notes