arch/powerpc/sysdev/xics/icp-native.c

Source file repositories/reference/linux-study-clean/arch/powerpc/sysdev/xics/icp-native.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/sysdev/xics/icp-native.c
Extension
.c
Size
7101 bytes
Lines
326
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration 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 icp_ipl {
	union {
		u32 word;
		u8 bytes[4];
	} xirr_poll;
	union {
		u32 word;
		u8 bytes[4];
	} xirr;
	u32 dummy;
	union {
		u32 word;
		u8 bytes[4];
	} qirr;
	u32 link_a;
	u32 link_b;
	u32 link_c;
};

static struct icp_ipl __iomem *icp_native_regs[NR_CPUS];

static inline unsigned int icp_native_get_xirr(void)
{
	int cpu = smp_processor_id();
	unsigned int xirr;

	/* Handled an interrupt latched by KVM */
	xirr = kvmppc_get_xics_latch();
	if (xirr)
		return xirr;

	return in_be32(&icp_native_regs[cpu]->xirr.word);
}

static inline void icp_native_set_xirr(unsigned int value)
{
	int cpu = smp_processor_id();

	out_be32(&icp_native_regs[cpu]->xirr.word, value);
}

static inline void icp_native_set_cppr(u8 value)
{
	int cpu = smp_processor_id();

	out_8(&icp_native_regs[cpu]->xirr.bytes[0], value);
}

static inline void icp_native_set_qirr(int n_cpu, u8 value)
{
	out_8(&icp_native_regs[n_cpu]->qirr.bytes[0], value);
}

static void icp_native_set_cpu_priority(unsigned char cppr)
{
	xics_set_base_cppr(cppr);
	icp_native_set_cppr(cppr);
	iosync();
}

void icp_native_eoi(struct irq_data *d)
{
	unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);

	iosync();
	icp_native_set_xirr((xics_pop_cppr() << 24) | hw_irq);
}

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

	/* Clear any pending IPI */
	icp_native_set_qirr(cpu, 0xff);
}

static void icp_native_flush_ipi(void)
{
	/* We take the ipi irq but and never return so we
	 * need to EOI the IPI, but want to leave our priority 0
	 *
	 * should we check all the other interrupts too?
	 * should we be flagging idle loop instead?
	 * or creating some task to be scheduled?
	 */

	icp_native_set_xirr((0x00 << 24) | XICS_IPI);
}

static unsigned int icp_native_get_irq(void)

Annotation

Implementation Notes