arch/powerpc/platforms/85xx/smp.c

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

File Facts

System
Linux kernel
Corpus path
arch/powerpc/platforms/85xx/smp.c
Extension
.c
Size
11808 bytes
Lines
523
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

struct epapr_spin_table {
	u32	addr_h;
	u32	addr_l;
	u32	r3_h;
	u32	r3_l;
	u32	reserved;
	u32	pir;
};

static u64 timebase;
static int tb_req;
static int tb_valid;

static void mpc85xx_give_timebase(void)
{
	unsigned long flags;

	local_irq_save(flags);
	hard_irq_disable();

	while (!tb_req)
		barrier();
	tb_req = 0;

	qoriq_pm_ops->freeze_time_base(true);
#ifdef CONFIG_PPC64
	/*
	 * e5500/e6500 have a workaround for erratum A-006958 in place
	 * that will reread the timebase until TBL is non-zero.
	 * That would be a bad thing when the timebase is frozen.
	 *
	 * Thus, we read it manually, and instead of checking that
	 * TBL is non-zero, we ensure that TB does not change.  We don't
	 * do that for the main mftb implementation, because it requires
	 * a scratch register
	 */
	{
		u64 prev;

		asm volatile("mfspr %0, %1" : "=r" (timebase) :
			     "i" (SPRN_TBRL));

		do {
			prev = timebase;
			asm volatile("mfspr %0, %1" : "=r" (timebase) :
				     "i" (SPRN_TBRL));
		} while (prev != timebase);
	}
#else
	timebase = get_tb();
#endif
	mb();
	tb_valid = 1;

	while (tb_valid)
		barrier();

	qoriq_pm_ops->freeze_time_base(false);

	local_irq_restore(flags);
}

static void mpc85xx_take_timebase(void)
{
	unsigned long flags;

	local_irq_save(flags);
	hard_irq_disable();

	tb_req = 1;
	while (!tb_valid)
		barrier();

	set_tb(timebase >> 32, timebase & 0xffffffff);
	isync();
	tb_valid = 0;

	local_irq_restore(flags);
}

#ifdef CONFIG_HOTPLUG_CPU
static void smp_85xx_cpu_offline_self(void)
{
	unsigned int cpu = smp_processor_id();

	local_irq_disable();
	hard_irq_disable();
	/* mask all irqs to prevent cpu wakeup */
	qoriq_pm_ops->irq_mask(cpu);

Annotation

Implementation Notes