Linux内核SMP机间中断(二)

在飞腾CPU平台上,SMP机间中断主要用来在指定CPU上实现七个目标:

IPI序号目标
IPI_RESCHEDULE

远程cpu执行任务调度

当被唤醒进程不是运行本地cpu上,就需要给被唤醒进程所在的远程cpu发送IPI中断,让远程cpu重新调度。在接收到IPI时无论远程cpu是否处于空闲态,被唤醒进程都会在IPI中断过渡到内核态时得到执行。

IPI_CALL_FUNC

远程cpu执行回调函数

当本地cpu将指定远程cpu调用的回调函数挂到远程cpu的队列上,然后给远程cpu发送IPI_CALL_FUNC机间中断;

远程cpu就会将执行队列上的所有回调函数,整个过程必须保持中断屏蔽状态。

IPI_CPU_STOP

远程CPU停止运行

先将指定的远程cpu从在线CPU位图中删除,然后将屏蔽D,A,I,F中断屏蔽,最后处理器进入低功耗循环。

IPI_CPU_CRASH_STOP

可选配置KEXEC_CORE

执行崩溃转储

IPI_TIMER

可选配置GENERIC_CLOCKEVENTS_BROADCAST

定时器广播

IPI_IRQ_WORK

可选配置IRQ_WORK

远程cpu在中断上下文中运行回调函数

IPI_WAKEUP

可选配置ARM64_ACPI_PARKING_PROTOCOL

唤醒CPU

1. 远程cpu执行任务调度

本地cpu端的Linux核心层通过函数smp_send_reschedule,向指定cpu发送“执行任务调度”需求。

void smp_send_reschedule(int cpu)
{
	smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
}

远程cpu端相应的中断处理

static __always_inline void scheduler_ipi(void)
{
	/*
	 * Fold TIF_NEED_RESCHED into the preempt_count; anybody setting
	 * TIF_NEED_RESCHED remotely (for the first time) will also send
	 * this IPI.
	 */
	preempt_fold_need_resched();
}

2. 远程cpu执行回调函数

本地cpu端的Linux核心层通过调用函数arch_send_call_function_xxx,向指定cpu发送“执行回调函数”需求。

void arch_send_call_function_ipi_mask(const struct cpumask *mask)
{
	smp_cross_call(mask, IPI_CALL_FUNC);
}

void arch_send_call_function_single_ipi(int cpu)
{
	smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC);
}

远程cpu端相应的中断处理

void generic_smp_call_function_single_interrupt(void)
{
	cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->gotipi, CFD_SEQ_NOCPU,
		      smp_processor_id(), CFD_SEQ_GOTIPI);
	flush_smp_call_function_queue(true);
}

3.远程CPU停止运行

本地cpu端发起machine_halt、machine_power_off、machine_restart等操作时,需要向其他所有cpu发送“停止运行”需求。

void smp_send_stop(void)

{
	unsigned long timeout;

	if (num_other_online_cpus()) {
		cpumask_t mask;

		cpumask_copy(&mask, cpu_online_mask);
		cpumask_clear_cpu(smp_processor_id(), &mask);

		if (system_state <= SYSTEM_RUNNING)
			pr_crit("SMP: stopping secondary CPUs\n");
		smp_cross_call(&mask, IPI_CPU_STOP);
	}

	/* Wait up to one second for other CPUs to stop */
	timeout = USEC_PER_SEC;
	while (num_other_online_cpus() && timeout--)
		udelay(1);

	if (num_other_online_cpus())
		pr_warn("SMP: failed to stop secondary CPUs %*pbl\n",
			cpumask_pr_args(cpu_online_mask));

	sdei_mask_local_cpu();
}

远程cpu端相应的中断处理

static void local_cpu_stop(void)
{
	set_cpu_online(smp_processor_id(), false);

	local_daif_mask();
	sdei_mask_local_cpu();
	cpu_park_loop();
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值