arch/arm/mach-zynq/platsmp.c

Source file repositories/reference/linux-study-clean/arch/arm/mach-zynq/platsmp.c

File Facts

System
Linux kernel
Corpus path
arch/arm/mach-zynq/platsmp.c
Extension
.c
Size
3989 bytes
Lines
164
Domain
Architecture Layer
Bucket
arch/arm
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

if (address) {
			if (__pa(PAGE_OFFSET)) {
				zero = ioremap(0, trampoline_code_size);
				if (!zero) {
					pr_warn("BOOTUP jump vectors not accessible\n");
					return -1;
				}
			} else {
				zero = (__force u8 __iomem *)PAGE_OFFSET;
			}

			/*
			* This is elegant way how to jump to any address
			* 0x0: Load address at 0x8 to r0
			* 0x4: Jump by mov instruction
			* 0x8: Jumping address
			*/
			memcpy_toio(zero, &zynq_secondary_trampoline,
							trampoline_size);
			writel(address, zero + trampoline_size);

			flush_cache_all();
			outer_flush_range(0, trampoline_code_size);
			smp_wmb();

			if (__pa(PAGE_OFFSET))
				iounmap(zero);
		}
		zynq_slcr_cpu_start(phy_cpuid);

		return 0;
	}

	pr_warn("Can't start CPU%d: Wrong starting address %x\n", cpu, address);

	return -1;
}
EXPORT_SYMBOL(zynq_cpun_start);

static int zynq_boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	return zynq_cpun_start(__pa_symbol(secondary_startup_arm), cpu);
}

/*
 * Initialise the CPU possible map early - this describes the CPUs
 * which may be present or become present in the system.
 */
static void __init zynq_smp_init_cpus(void)
{
	int i;

	ncores = scu_get_core_count(zynq_scu_base);

	for (i = 0; i < ncores && i < CONFIG_NR_CPUS; i++)
		set_cpu_possible(i, true);
}

static void __init zynq_smp_prepare_cpus(unsigned int max_cpus)
{
	scu_enable(zynq_scu_base);
}

/**
 * zynq_secondary_init - Initialize secondary CPU cores
 * @cpu:	CPU that is initialized
 *
 * This function is in the hotplug path. Don't move it into the
 * init section!!
 */
static void zynq_secondary_init(unsigned int cpu)
{
	zynq_core_pm_init();
}

#ifdef CONFIG_HOTPLUG_CPU
static int zynq_cpu_kill(unsigned cpu)
{
	unsigned long timeout = jiffies + msecs_to_jiffies(50);

	while (zynq_slcr_cpu_state_read(cpu))
		if (time_after(jiffies, timeout))
			return 0;

	zynq_slcr_cpu_stop(cpu);
	return 1;
}

/**
 * zynq_cpu_die - Let a CPU core die

Annotation

Implementation Notes