arch/mips/loongson64/smp.c

Source file repositories/reference/linux-study-clean/arch/mips/loongson64/smp.c

File Facts

System
Linux kernel
Corpus path
arch/mips/loongson64/smp.c
Extension
.c
Size
28820 bytes
Lines
859
Domain
Architecture Layer
Bucket
arch/mips
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

if (loongson_sysconf.reserved_cpus_mask & (1<<i)) {
			/* Reserved physical CPU cores */
			__cpu_number_map[i] = -1;
		} else {
			__cpu_number_map[i] = num;
			__cpu_logical_map[num] = i;
			set_cpu_possible(num, true);
			/* Loongson processors are always grouped by 4 */
			cpu_set_cluster(&cpu_data[num], i / 4);
			num++;
		}
		i++;
	}
	pr_info("Detected %i available CPU(s)\n", num);

	while (num < loongson_sysconf.nr_cpus) {
		__cpu_logical_map[num] = -1;
		num++;
	}
	csr_ipi_probe();
	ipi_set0_regs_init();
	ipi_clear0_regs_init();
	ipi_status0_regs_init();
	ipi_en0_regs_init();
	ipi_mailbox_buf_init();
	if (smp_group[0])
		ipi_write_enable(0);

	cpu_set_core(&cpu_data[0],
		     cpu_logical_map(0) % loongson_sysconf.cores_per_package);
	cpu_data[0].package = cpu_logical_map(0) / loongson_sysconf.cores_per_package;
}

static void __init loongson3_prepare_cpus(unsigned int max_cpus)
{
	if (request_irq(LS_IPI_IRQ, loongson3_ipi_interrupt,
			IRQF_PERCPU | IRQF_NO_SUSPEND, "SMP_IPI", NULL))
		pr_err("Failed to request IPI IRQ\n");
	init_cpu_present(cpu_possible_mask);
	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
}

/*
 * Setup the PC, SP, and GP of a secondary processor and start it running!
 */
static int loongson3_boot_secondary(int cpu, struct task_struct *idle)
{
	pr_info("Booting CPU#%d...\n", cpu);

	ipi_write_buf(cpu, idle);

	return 0;
}

#ifdef CONFIG_HOTPLUG_CPU

static int loongson3_cpu_disable(void)
{
	unsigned long flags;
	unsigned int cpu = smp_processor_id();

	set_cpu_online(cpu, false);
	calculate_cpu_foreign_map();
	local_irq_save(flags);
	clear_c0_status(ST0_IM);
	local_irq_restore(flags);
	local_flush_tlb_all();

	return 0;
}


static void loongson3_cpu_die(unsigned int cpu)
{
	while (per_cpu(cpu_state, cpu) != CPU_DEAD)
		cpu_relax();

	mb();
}

/* To shutdown a core in Loongson 3, the target core should go to CKSEG1 and
 * flush all L1 entries at first. Then, another core (usually Core 0) can
 * safely disable the clock of the target core. loongson3_play_dead() is
 * called via CKSEG1 (uncached and unmmaped)
 */
static void loongson3_type1_play_dead(int *state_addr)
{
	register int val;
	register long cpuid, core, node, count;
	register void *addr, *base, *initfunc;

Annotation

Implementation Notes