arch/sparc/kernel/sun4d_smp.c

Source file repositories/reference/linux-study-clean/arch/sparc/kernel/sun4d_smp.c

File Facts

System
Linux kernel
Corpus path
arch/sparc/kernel/sun4d_smp.c
Extension
.c
Size
9880 bytes
Lines
416
Domain
Architecture Layer
Bucket
arch/sparc
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 sun4d_ipi_work {
	int single;
	int msk;
	int resched;
};

static DEFINE_PER_CPU_SHARED_ALIGNED(struct sun4d_ipi_work, sun4d_ipi_work);

/* Initialize IPIs on the SUN4D SMP machine */
static void __init smp4d_ipi_init(void)
{
	int cpu;
	struct sun4d_ipi_work *work;

	printk(KERN_INFO "smp4d: setup IPI at IRQ %d\n", SUN4D_IPI_IRQ);

	for_each_possible_cpu(cpu) {
		work = &per_cpu(sun4d_ipi_work, cpu);
		work->single = work->msk = work->resched = 0;
	}
}

void sun4d_ipi_interrupt(void)
{
	struct sun4d_ipi_work *work = this_cpu_ptr(&sun4d_ipi_work);

	if (work->single) {
		work->single = 0;
		smp_call_function_single_interrupt();
	}
	if (work->msk) {
		work->msk = 0;
		smp_call_function_interrupt();
	}
	if (work->resched) {
		work->resched = 0;
		smp_resched_interrupt();
	}
}

/* +-------+-------------+-----------+------------------------------------+
 * | bcast |  devid      |   sid     |              levels mask           |
 * +-------+-------------+-----------+------------------------------------+
 *  31      30         23 22       15 14                                 0
 */
#define IGEN_MESSAGE(bcast, devid, sid, levels) \
	(((bcast) << 31) | ((devid) << 23) | ((sid) << 15) | (levels))

static void sun4d_send_ipi(int cpu, int level)
{
	cc_set_igen(IGEN_MESSAGE(0, cpu << 3, 6 + ((level >> 1) & 7), 1 << (level - 1)));
}

static void sun4d_ipi_single(int cpu)
{
	struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);

	/* Mark work */
	work->single = 1;

	/* Generate IRQ on the CPU */
	sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
}

static void sun4d_ipi_mask_one(int cpu)
{
	struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);

	/* Mark work */
	work->msk = 1;

	/* Generate IRQ on the CPU */
	sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
}

static void sun4d_ipi_resched(int cpu)
{
	struct sun4d_ipi_work *work = &per_cpu(sun4d_ipi_work, cpu);

	/* Mark work */
	work->resched = 1;

	/* Generate IRQ on the CPU (any IRQ will cause resched) */
	sun4d_send_ipi(cpu, SUN4D_IPI_IRQ);
}

static struct smp_funcall {
	void *func;
	unsigned long arg1;
	unsigned long arg2;

Annotation

Implementation Notes