OpenCores
URL https://opencores.org/ocsvn/c0or1k/c0or1k/trunk

Subversion Repositories c0or1k

[/] [c0or1k/] [trunk/] [src/] [glue/] [arm/] [smp.c] - Rev 6

Go to most recent revision | Compare with Previous | Blame | View Log

/*
 * Copyright (C) 2010 B Labs Ltd.
 *
 * Authors: Prem Mallappa, Bahadir Balban
 *
 * SMP Initialization of cores.
 */
 
#include <l4/generic/platform.h>
#include INC_GLUE(smp.h)
#include INC_GLUE(init.h)
#include INC_GLUE(mapping.h)
#include INC_SUBARCH(cpu.h)
#include INC_SUBARCH(proc.h)
#include INC_SUBARCH(mmu_ops.h)
#include INC_ARCH(linker.h)
#include INC_ARCH(io.h)
#include <l4/drivers/irq/gic/gic.h>
 
unsigned long secondary_run_signal;
unsigned long secondary_ready_signal;
 
void __smp_start(void);
 
void smp_start_cores(void)
{
	void (*smp_start_func)(int) =
		(void (*)(int))virt_to_phys(__smp_start);
 
	/* FIXME: Check why this high-level version doesn't work */
	// v7_up_dcache_op_setway(CACHE_SETWAY_CLEAN);
	v7_clean_invalidate_setway();
 
	/* We dont probably need this, it is not listed as a requirement */
	arm_smp_inval_icache_entirely();
 
	/* Start other cpus */
	for (int cpu = 1; cpu < CONFIG_NCPU; cpu++) {
		printk("%s: Bringing up CPU%d\n", __KERNELNAME__, cpu);
		if ((platform_smp_start(cpu, smp_start_func)) < 0) {
			printk("FATAL: Could not start secondary cpu. "
			       "cpu=%d\n", cpu);
			BUG();
		}
 
		/* Wait for this particular secondary to become ready */
		while(!(secondary_ready_signal & CPUID_TO_MASK(cpu)))
			dmb();
	}
 
	scu_print_state();
}
 
void init_smp(void)
{
	/* Start_secondary_cpus */
	if (CONFIG_NCPU > 1) {
		/* This sets IPI function pointer at bare minimum */
		platform_smp_init(CONFIG_NCPU);
	}
}
 
void secondary_setup_idle_task(void)
{
	/* This also has its spid allocated by primary */
	current->space = &init_space;
	TASK_PGD(current) = &init_pgd;
 
	/* We need a thread id */
	current->tid = id_new(&kernel_resources.ktcb_ids);
}
 
/*
 * Idle wait before any tasks become available for running.
 *
 * FIXME: This should be changed such that tasks running on other
 * cpus can be killed and secondaries wait on an idle task.
 *
 * Currently the tasks are held in wfi() even if asked to be killed
 * until a new runnable task becomes runnable. This may be problematic
 * for a pager who issued a kill request and is waiting for it to finish.
 */
void sched_secondary_start(void)
{
	while (!secondary_run_signal)
		dmb();
 
	secondary_setup_idle_task();
 
	setup_idle_caps();
 
	idle_task();
 
	BUG();
}
 
 
/*
 * this is where it jumps from secondary_start(), which is called from
 * board_smp_start() to align each core to start here
 */
 
void smp_secondary_init(void)
{
	/* Print early core start message */
	// print_early("Secondary core started.\n");
 
	/* Start virtual memory */
	start_virtual_memory();
 
	arm_smp_inval_tlb_entirely();
	arm_smp_inval_bpa_entirely();
	dsb();
	isb();
 
	printk("%s: CPU%d: Virtual memory enabled.\n",
	       __KERNELNAME__, smp_get_cpuid());
 
	/* Mostly initialize GIC CPU interface */
	secondary_init_platform();
 
	printk("%s: CPU%d: Initialized.\n",
	       __KERNELNAME__, smp_get_cpuid());
 
	sched_init();
 
	/* Signal primary that we are ready */
	dmb();
	secondary_ready_signal |= cpu_mask_self();
 
	/*
	 * Wait for the first runnable task to become available
	 */
	sched_secondary_start();
}
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.