242 lines · 4.8 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * Copyright (C) 2025 Ant Group * Author: Tiwei Bie <tiwei.btw@antgroup.com> * * Based on the previous implementation in TT mode * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) */ #include <linux/sched.h>#include <linux/sched/task.h>#include <linux/sched/task_stack.h>#include <linux/module.h>#include <linux/processor.h>#include <linux/threads.h>#include <linux/cpu.h>#include <linux/hardirq.h>#include <linux/smp.h>#include <linux/smp-internal.h>#include <init.h>#include <kern.h>#include <os.h>#include <smp.h> enum {	UML_IPI_RES = 0,	UML_IPI_CALL_SINGLE,	UML_IPI_CALL,	UML_IPI_STOP,}; void arch_smp_send_reschedule(int cpu){	os_send_ipi(cpu, UML_IPI_RES);} void arch_send_call_function_single_ipi(int cpu){	os_send_ipi(cpu, UML_IPI_CALL_SINGLE);} void arch_send_call_function_ipi_mask(const struct cpumask *mask){	int cpu; 	for_each_cpu(cpu, mask)		os_send_ipi(cpu, UML_IPI_CALL);} void smp_send_stop(void){	int cpu, me = smp_processor_id(); 	for_each_online_cpu(cpu) {		if (cpu == me)			continue;		os_send_ipi(cpu, UML_IPI_STOP);	}} static void ipi_handler(int vector, struct uml_pt_regs *regs){	struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);	int cpu = raw_smp_processor_id(); 	irq_enter(); 	if (current->mm)		os_alarm_process(current->mm->context.id.pid); 	switch (vector) {	case UML_IPI_RES:		inc_irq_stat(irq_resched_count);		scheduler_ipi();		break; 	case UML_IPI_CALL_SINGLE:		inc_irq_stat(irq_call_count);		generic_smp_call_function_single_interrupt();		break; 	case UML_IPI_CALL:		inc_irq_stat(irq_call_count);		generic_smp_call_function_interrupt();		break; 	case UML_IPI_STOP:		set_cpu_online(cpu, false);		while (1)			pause();		break; 	default:		pr_err("CPU#%d received unknown IPI (vector=%d)!\n", cpu, vector);		break;	} 	irq_exit();	set_irq_regs(old_regs);} void uml_ipi_handler(int vector){	struct uml_pt_regs r = { .is_user = 0 }; 	preempt_disable();	ipi_handler(vector, &r);	preempt_enable();} /* AP states used only during CPU startup */enum {	UML_CPU_PAUSED = 0,	UML_CPU_RUNNING,}; static int cpu_states[NR_CPUS]; static int start_secondary(void *unused){	int err, cpu = raw_smp_processor_id(); 	notify_cpu_starting(cpu);	set_cpu_online(cpu, true); 	err = um_setup_timer();	if (err)		panic("CPU#%d failed to setup timer, err = %d", cpu, err); 	local_irq_enable(); 	cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); 	return 0;} void uml_start_secondary(void *opaque){	int cpu = raw_smp_processor_id();	struct mm_struct *mm = &init_mm;	struct task_struct *idle; 	stack_protections((unsigned long) &cpu_irqstacks[cpu]);	set_sigstack(&cpu_irqstacks[cpu], THREAD_SIZE); 	set_cpu_present(cpu, true);	os_futex_wait(&cpu_states[cpu], UML_CPU_PAUSED); 	smp_rmb(); /* paired with smp_wmb() in __cpu_up() */ 	idle = cpu_tasks[cpu];	idle->thread_info.cpu = cpu; 	mmgrab(mm);	idle->active_mm = mm; 	idle->thread.request.thread.proc = start_secondary;	idle->thread.request.thread.arg = NULL; 	new_thread(task_stack_page(idle), &idle->thread.switch_buf,		   new_thread_handler);	os_start_secondary(opaque, &idle->thread.switch_buf);} void __init smp_prepare_cpus(unsigned int max_cpus){	int err, cpu, me = smp_processor_id();	unsigned long deadline; 	os_init_smp(); 	for_each_possible_cpu(cpu) {		if (cpu == me)			continue; 		pr_debug("Booting processor %d...\n", cpu);		err = os_start_cpu_thread(cpu);		if (err) {			pr_crit("CPU#%d failed to start cpu thread, err = %d",				cpu, err);			continue;		} 		deadline = jiffies + msecs_to_jiffies(1000);		spin_until_cond(cpu_present(cpu) ||				time_is_before_jiffies(deadline)); 		if (!cpu_present(cpu))			pr_crit("CPU#%d failed to boot\n", cpu);	}} int __cpu_up(unsigned int cpu, struct task_struct *tidle){	cpu_tasks[cpu] = tidle;	smp_wmb(); /* paired with smp_rmb() in uml_start_secondary() */	cpu_states[cpu] = UML_CPU_RUNNING;	os_futex_wake(&cpu_states[cpu]);	spin_until_cond(cpu_online(cpu)); 	return 0;} void __init smp_cpus_done(unsigned int max_cpus){} /* Set in uml_ncpus_setup */int uml_ncpus = 1; void __init prefill_possible_map(void){	int cpu; 	for (cpu = 0; cpu < uml_ncpus; cpu++)		set_cpu_possible(cpu, true);	for (; cpu < NR_CPUS; cpu++)		set_cpu_possible(cpu, false);} static int __init uml_ncpus_setup(char *line, int *add){	*add = 0; 	if (kstrtoint(line, 10, &uml_ncpus)) {		os_warn("%s: Couldn't parse '%s'\n", __func__, line);		return -1;	} 	uml_ncpus = clamp(uml_ncpus, 1, NR_CPUS); 	return 0;} __uml_setup("ncpus=", uml_ncpus_setup,"ncpus=<# of desired CPUs>\n""    This tells UML how many virtual processors to start. The maximum\n""    number of supported virtual processors can be obtained by querying\n""    the CONFIG_NR_CPUS option using --showconfig.\n\n"); EXPORT_SYMBOL(uml_curr_cpu);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t