Esempio n. 1
0
/* Fill in cpu_info structures according to device tree. */
static void init_cpu_info(struct bus *bus)
{
	device_t cur;

	for (cur = bus->children; cur != NULL; cur = cur->sibling) {
		struct cpu_info *ci;
		unsigned int id = cur->path.cpu.id;

		if (cur->path.type != DEVICE_PATH_CPU)
			continue;

		/* IDs are currently mapped 1:1 with logical CPU numbers. */
		if (id >= CONFIG_MAX_CPUS) {
			printk(BIOS_WARNING,
				"CPU id %x too large. Disabling.\n", id);
			cpu_disable_dev(cur);
			continue;
		}

		ci = cpu_info_for_cpu(id);
		if (ci->cpu != NULL) {
			printk(BIOS_WARNING,
				"Duplicate ID %x in device tree.\n", id);
			cpu_disable_dev(cur);
		}

		ci->cpu = cur;
		ci->id = cur->path.cpu.id;
	}
}
Esempio n. 2
0
static int __arch_run_on_all_cpus(struct cpu_action *action, int sync)
{
	int i;

	for (i = 0; i < CONFIG_MAX_CPUS; i++)
		action_run_on_cpu(cpu_info_for_cpu(i), action, sync);

	return 0;
}
Esempio n. 3
0
size_t cpus_online(void)
{
	int i;
	size_t num = 0;

	for (i = 0; i < ARRAY_SIZE(cpu_infos); i++) {
		if (cpu_online(cpu_info_for_cpu(i)))
			num++;
	}

	return num;
}
Esempio n. 4
0
static int __arch_run_on_all_cpus_but_self(struct cpu_action *action, int sync)
{
	int i;
	struct cpu_info *me = cpu_info();

	for (i = 0; i < CONFIG_MAX_CPUS; i++) {
		struct cpu_info *ci = cpu_info_for_cpu(i);
		if (ci == me)
			continue;
		action_run_on_cpu(ci, action, sync);
	}

	return 0;
}
Esempio n. 5
0
static int __arch_run_on_cpu(unsigned int cpu, struct cpu_action *action,
				int sync)
{
	struct cpu_info *ci;

	if (cpu >= CONFIG_MAX_CPUS)
		return -1;

	ci = cpu_info_for_cpu(cpu);

	action_run_on_cpu(ci, action, sync);

	return 0;
}
Esempio n. 6
0
void arch_initialize_cpus(device_t cluster, struct cpu_control_ops *cntrl_ops)
{
	size_t max_cpus;
	size_t i;
	struct cpu_info *ci;
	void (*entry)(void);
	struct bus *bus;

	if (cluster->path.type != DEVICE_PATH_CPU_CLUSTER) {
		printk(BIOS_ERR,
			"CPU init failed. Device is not a CPU_CLUSTER: %s\n",
			dev_path(cluster));
		return;
	}

	bus = cluster->link_list;

	/* Check if no children under this device. */
	if (bus == NULL)
		return;

	/*
	 * el3_init must be performed prior to prepare_secondary_cpu_startup.
	 * This is important since el3_init initializes SCR values on BSP CPU
	 * and then prepare_secondary_cpu_startup reads the initialized SCR
	 * value and saves it for use by non-BSP CPUs.
	 */
	el3_init();
	/* Mark current cpu online. */
	cpu_mark_online(cpu_info());
	entry = prepare_secondary_cpu_startup();

	/* Initialize the cpu_info structures. */
	init_cpu_info(bus);
	max_cpus = cntrl_ops->total_cpus();

	if (max_cpus > CONFIG_MAX_CPUS) {
		printk(BIOS_WARNING,
			"max_cpus (%zu) exceeds CONFIG_MAX_CPUS (%zu).\n",
			max_cpus, (size_t)CONFIG_MAX_CPUS);
		max_cpus = CONFIG_MAX_CPUS;
	}

	for (i = 0; i < max_cpus; i++) {
		device_t dev;
		struct cpu_action action;
		struct stopwatch sw;

		ci = cpu_info_for_cpu(i);
		dev = ci->cpu;

		/* Disregard CPUs not in device tree. */
		if (dev == NULL)
			continue;

		/* Skip disabled CPUs. */
		if (!dev->enabled)
			continue;

		if (!cpu_online(ci)) {
			/* Start the CPU. */
			printk(BIOS_DEBUG, "Starting CPU%x\n", ci->id);

			if (cntrl_ops->start_cpu(ci->id, entry)) {
				printk(BIOS_ERR,
					"Failed to start CPU%x\n", ci->id);
				continue;
			}
			stopwatch_init_msecs_expire(&sw, 1000);
			/* Wait for CPU to come online. */
			while (!stopwatch_expired(&sw)) {
				if (!cpu_online(ci))
					continue;
				printk(BIOS_DEBUG,
					"CPU%x online in %ld usecs.\n",
					ci->id, stopwatch_duration_usecs(&sw));
				break;
			}
		}

		if (!cpu_online(ci)) {
			printk(BIOS_DEBUG,
				"CPU%x failed to come online in %ld usecs.\n",
				ci->id, stopwatch_duration_usecs(&sw));
			continue;
		}

		/* Send it the init action. */
		action.run = init_this_cpu;
		action.arg = ci;
		arch_run_on_cpu(ci->id, &action);
	}
}
Esempio n. 7
0
struct cpu_info *cpu_info(void)
{
	return cpu_info_for_cpu(smp_processor_id());
}