arch/powerpc/include/asm/entry-common.h

Source file repositories/reference/linux-study-clean/arch/powerpc/include/asm/entry-common.h

File Facts

System
Linux kernel
Corpus path
arch/powerpc/include/asm/entry-common.h
Extension
.h
Size
14911 bytes
Lines
535
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 interrupt_nmi_state {
#ifdef CONFIG_PPC64
	u8 irq_soft_mask;
	u8 irq_happened;
	u8 ftrace_enabled;
	u64 softe;
#endif
};

static inline bool nmi_disables_ftrace(struct pt_regs *regs)
{
	/* Allow DEC and PMI to be traced when they are soft-NMI */
	if (IS_ENABLED(CONFIG_PPC_BOOK3S_64)) {
		if (TRAP(regs) == INTERRUPT_DECREMENTER)
			return false;
		if (TRAP(regs) == INTERRUPT_PERFMON)
			return false;
	}
	if (IS_ENABLED(CONFIG_PPC_BOOK3E_64)) {
		if (TRAP(regs) == INTERRUPT_PERFMON)
			return false;
	}

	return true;
}

static inline void arch_interrupt_nmi_enter_prepare(struct pt_regs *regs,
						    struct interrupt_nmi_state *state)
{
#ifdef CONFIG_PPC64
	state->irq_soft_mask = local_paca->irq_soft_mask;
	state->irq_happened = local_paca->irq_happened;
	state->softe = regs->softe;

	/*
	 * Set IRQS_ALL_DISABLED unconditionally so irqs_disabled() does
	 * the right thing, and set IRQ_HARD_DIS. We do not want to reconcile
	 * because that goes through irq tracing which we don't want in NMI.
	 */
	local_paca->irq_soft_mask = IRQS_ALL_DISABLED;
	local_paca->irq_happened |= PACA_IRQ_HARD_DIS;

	if (!(regs->msr & MSR_EE) || is_implicit_soft_masked(regs)) {
		/*
		 * Adjust regs->softe to be soft-masked if it had not been
		 * reconcied (e.g., interrupt entry with MSR[EE]=0 but softe
		 * not yet set disabled), or if it was in an implicit soft
		 * masked state. This makes regs_irqs_disabled(regs)
		 * behave as expected.
		 */
		regs->softe = IRQS_ALL_DISABLED;
	}

	__hard_RI_enable();

	/* Don't do any per-CPU operations until interrupt state is fixed */

	if (nmi_disables_ftrace(regs)) {
		state->ftrace_enabled = this_cpu_get_ftrace_enabled();
		this_cpu_set_ftrace_enabled(0);
	}
#endif
}

static inline void arch_interrupt_nmi_exit_prepare(struct pt_regs *regs,
						   struct interrupt_nmi_state *state)
{
	/*
	 * nmi does not call nap_adjust_return because nmi should not create
	 * new work to do (must use irq_work for that).
	 */

#ifdef CONFIG_PPC64
#ifdef CONFIG_PPC_BOOK3S
	if (regs_irqs_disabled(regs)) {
		unsigned long rst = search_kernel_restart_table(regs->nip);

		if (rst)
			regs_set_return_ip(regs, rst);
	}
#endif

	if (nmi_disables_ftrace(regs))
		this_cpu_set_ftrace_enabled(state->ftrace_enabled);

	/* Check we didn't change the pending interrupt mask. */
	WARN_ON_ONCE((state->irq_happened | PACA_IRQ_HARD_DIS) != local_paca->irq_happened);
	regs->softe = state->softe;
	local_paca->irq_happened = state->irq_happened;
	local_paca->irq_soft_mask = state->irq_soft_mask;

Annotation

Implementation Notes