All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support for Minnowboard MAX
@ 2015-04-30  4:25 Simon Glass
  2015-04-30  4:25 ` [U-Boot] [PATCH v3 1/5] x86: Add multi-processor init Simon Glass
                   ` (5 more replies)
  0 siblings, 6 replies; 18+ messages in thread
From: Simon Glass @ 2015-04-30  4:25 UTC (permalink / raw)
  To: u-boot

This series adds a new CPU uclass which is intended to be useful on any
architecture. So far it has a very simple interface and a command to show
CPU details.

This series also introduces multi-core init for x86. It is implemented and
enabled on Minnowboard MAX, a single/dual-core Atom board. The CPU uclass is
implemented for x86 and the Simple Firmware Interface provides these details
to the kernel, since ACPI is not yet available.

With these changes Minnowboard MAX can boot into Linux with both cores
enabled.

This series is available at u-boot-x86 branch 'cpu-working'.

Changes in v3:
- Rename CONFIG_STACK_SIZE to CONFIG_AP_STACK_SIZE
- Remove sipi_vector_location and sipi_vector_location_size variables
- Remove annoying /* 1ms */ comments
- Rename sipi.S to sipi_vector.S
- Correct 'ap_start32' to 'ap_start'
- Use macros for cr0 bit fields
- Correct style in a multi-line comment
- Use UCODE_HEADER_LEN instead of 48
- Remove unnecessary underscores in MP_FR_BLOCK_APS and MP_FR_NOBLOCK_APS
- Use 'cpu number' instead of 'coreboot cpu number'
- Remove a stray blank line in sipi.h
- Enhance comment for @microcode_lock
- Rename SMM_DEFAULT_BASE/SIZE to AP_DEFAULT_BASE/SIZE and drop smm.h
- Use data32 instead of our own 'o32'
- Move NUM_FIXED_MTRRS to mtrr.h
- Avoid using asmlinkage on ap_init()
- Add msr_clrbits_64() too
- Collect all new MSRs into msr-index.h
- Spell 'BayTrail' like so
- Make set_max_freq() static

Changes in v2:
- Correct 'I2C uclass' typo
- Add blank line in x86_cpu_get_desc()

Simon Glass (5):
  x86: Add multi-processor init
  x86: Add functions to set and clear bits on MSRs
  x86: Allow CPUs to be set up after relocation
  x86: Add a CPU driver for baytrail
  x86: Enable multi-core init for Minnowboard MAX

 arch/x86/Kconfig                                  |  30 ++
 arch/x86/cpu/Makefile                             |   2 +
 arch/x86/cpu/baytrail/Makefile                    |   1 +
 arch/x86/cpu/baytrail/cpu.c                       | 205 +++++++++
 arch/x86/cpu/cpu.c                                |  38 ++
 arch/x86/cpu/ivybridge/car.S                      |   1 +
 arch/x86/cpu/ivybridge/model_206ax.c              |   4 +-
 arch/x86/cpu/mp_init.c                            | 496 ++++++++++++++++++++++
 arch/x86/cpu/sipi_vector.S                        | 216 ++++++++++
 arch/x86/dts/minnowmax.dts                        |  20 +
 arch/x86/include/asm/arch-ivybridge/microcode.h   |   3 -
 arch/x86/include/asm/arch-ivybridge/model_206ax.h |   2 -
 arch/x86/include/asm/cpu.h                        |  14 +
 arch/x86/include/asm/mp.h                         |  94 ++++
 arch/x86/include/asm/msr-index.h                  |  22 +-
 arch/x86/include/asm/msr.h                        |  28 ++
 arch/x86/include/asm/mtrr.h                       |   6 +-
 arch/x86/include/asm/processor.h                  |   3 +
 arch/x86/include/asm/sipi.h                       |  86 ++++
 arch/x86/include/asm/turbo.h                      |   3 -
 arch/x86/include/asm/u-boot-x86.h                 |   2 +
 common/board_r.c                                  |   2 +-
 configs/minnowmax_defconfig                       |   4 +
 23 files changed, 1268 insertions(+), 14 deletions(-)
 create mode 100644 arch/x86/cpu/baytrail/cpu.c
 create mode 100644 arch/x86/cpu/mp_init.c
 create mode 100644 arch/x86/cpu/sipi_vector.S
 create mode 100644 arch/x86/include/asm/mp.h
 create mode 100644 arch/x86/include/asm/sipi.h

-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 1/5] x86: Add multi-processor init
  2015-04-30  4:25 [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support for Minnowboard MAX Simon Glass
@ 2015-04-30  4:25 ` Simon Glass
  2015-04-30  6:09   ` Bin Meng
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 2/5] x86: Add functions to set and clear bits on MSRs Simon Glass
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: Simon Glass @ 2015-04-30  4:25 UTC (permalink / raw)
  To: u-boot

Most modern x86 CPUs include more than one CPU core. The OS normally requires
that these 'Application Processors' (APs) be brought up by the boot loader.
Add the required support to U-Boot to init additional APs.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Rename CONFIG_STACK_SIZE to CONFIG_AP_STACK_SIZE
- Remove sipi_vector_location and sipi_vector_location_size variables
- Remove annoying /* 1ms */ comments
- Rename sipi.S to sipi_vector.S
- Correct 'ap_start32' to 'ap_start'
- Use macros for cr0 bit fields
- Correct style in a multi-line comment
- Use UCODE_HEADER_LEN instead of 48
- Remove unnecessary underscores in MP_FR_BLOCK_APS and MP_FR_NOBLOCK_APS
- Use 'cpu number' instead of 'coreboot cpu number'
- Remove a stray blank line in sipi.h
- Enhance comment for @microcode_lock
- Rename SMM_DEFAULT_BASE/SIZE to AP_DEFAULT_BASE/SIZE and drop smm.h
- Use data32 instead of our own 'o32'
- Move NUM_FIXED_MTRRS to mtrr.h
- Avoid using asmlinkage on ap_init()

Changes in v2: None

 arch/x86/Kconfig                                |  30 ++
 arch/x86/cpu/Makefile                           |   2 +
 arch/x86/cpu/ivybridge/car.S                    |   1 +
 arch/x86/cpu/ivybridge/model_206ax.c            |   4 +-
 arch/x86/cpu/mp_init.c                          | 496 ++++++++++++++++++++++++
 arch/x86/cpu/sipi_vector.S                      | 216 +++++++++++
 arch/x86/include/asm/arch-ivybridge/microcode.h |   3 -
 arch/x86/include/asm/mp.h                       |  94 +++++
 arch/x86/include/asm/mtrr.h                     |   6 +-
 arch/x86/include/asm/processor.h                |   3 +
 arch/x86/include/asm/sipi.h                     |  86 ++++
 11 files changed, 934 insertions(+), 7 deletions(-)
 create mode 100644 arch/x86/cpu/mp_init.c
 create mode 100644 arch/x86/cpu/sipi_vector.S
 create mode 100644 arch/x86/include/asm/mp.h
 create mode 100644 arch/x86/include/asm/sipi.h

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 467fe25..8e734fd 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -361,6 +361,36 @@ config FSP_TEMP_RAM_ADDR
 	  Stack top address which is used in FspInit after DRAM is ready and
 	  CAR is disabled.
 
+config MAX_CPUS
+        int "Maximum number of CPUs permitted"
+        default 4
+        help
+          When using multi-CPU chips it is possible for U-Boot to start up
+          more than one CPU. The stack memory used by all of these CPUs is
+          pre-allocated so at present U-Boot wants to know the maximum
+          number of CPUs that may be present. Set this to at least as high
+          as the number of CPUs in your system (it uses about 4KB of RAM for
+          each CPU).
+
+config SMP
+	bool "Enable Symmetric Multiprocessing"
+	default n
+	help
+	  Enable use of more than one CPU in U-Boot and the Operating System
+	  when loaded. Each CPU will be started up and information can be
+	  obtained using the 'cpu' command. If this option is disabled, then
+	  only one CPU will be enabled regardless of the number of CPUs
+	  available.
+
+config AP_STACK_SIZE
+	hex
+	default 0x1000
+	help
+	  Each additional CPU started by U-Boot requires its own stack. This
+	  option sets the stack size used by each CPU and directly affects
+	  the memory used by this initialisation process. Typically 4KB is
+	  enough space.
+
 config TSC_CALIBRATION_BYPASS
 	bool "Bypass Time-Stamp Counter (TSC) calibration"
 	default n
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
index 6ded0a7..043bea2 100644
--- a/arch/x86/cpu/Makefile
+++ b/arch/x86/cpu/Makefile
@@ -19,6 +19,8 @@ obj-$(CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE) += ivybridge/
 obj-$(CONFIG_INTEL_QUARK) += quark/
 obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
 obj-y += lapic.o
+obj-$(CONFIG_SMP) += mp_init.o
 obj-y += mtrr.o
 obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_SMP) += sipi_vector.o
 obj-y += turbo.o
diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S
index 9441666..407e451 100644
--- a/arch/x86/cpu/ivybridge/car.S
+++ b/arch/x86/cpu/ivybridge/car.S
@@ -15,6 +15,7 @@
 #include <asm/msr-index.h>
 #include <asm/mtrr.h>
 #include <asm/post.h>
+#include <asm/processor.h>
 #include <asm/processor-flags.h>
 #include <asm/arch/microcode.h>
 
diff --git a/arch/x86/cpu/ivybridge/model_206ax.c b/arch/x86/cpu/ivybridge/model_206ax.c
index 11dc625..8b08c40 100644
--- a/arch/x86/cpu/ivybridge/model_206ax.c
+++ b/arch/x86/cpu/ivybridge/model_206ax.c
@@ -435,8 +435,8 @@ static int intel_cores_init(struct x86_cpu_priv *cpu)
 
 		debug("CPU: %u has core %u\n", cpu->apic_id, new_cpu->apic_id);
 
-#if CONFIG_SMP && CONFIG_MAX_CPUS > 1
-		/* Start the new cpu */
+#if 0 && CONFIG_SMP && CONFIG_MAX_CPUS > 1
+		/* TODO(sjg at chromium.org): Start the new cpu */
 		if (!start_cpu(new_cpu)) {
 			/* Record the error in cpu? */
 			printk(BIOS_ERR, "CPU %u would not start!\n",
diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c
new file mode 100644
index 0000000..ac5753a
--- /dev/null
+++ b/arch/x86/cpu/mp_init.c
@@ -0,0 +1,496 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Based on code from the coreboot file of the same name
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <errno.h>
+#include <malloc.h>
+#include <asm/atomic.h>
+#include <asm/cpu.h>
+#include <asm/interrupt.h>
+#include <asm/lapic.h>
+#include <asm/mp.h>
+#include <asm/mtrr.h>
+#include <asm/sipi.h>
+#include <dm/device-internal.h>
+#include <dm/uclass-internal.h>
+#include <linux/linkage.h>
+
+/* This also needs to match the sipi.S assembly code for saved MSR encoding */
+struct saved_msr {
+	uint32_t index;
+	uint32_t lo;
+	uint32_t hi;
+} __packed;
+
+
+struct mp_flight_plan {
+	int num_records;
+	struct mp_flight_record *records;
+};
+
+static struct mp_flight_plan mp_info;
+
+struct cpu_map {
+	struct udevice *dev;
+	int apic_id;
+	int err_code;
+};
+
+static inline void barrier_wait(atomic_t *b)
+{
+	while (atomic_read(b) == 0)
+		asm("pause");
+	mfence();
+}
+
+static inline void release_barrier(atomic_t *b)
+{
+	mfence();
+	atomic_set(b, 1);
+}
+
+/* Returns 1 if timeout waiting for APs. 0 if target APs found */
+static int wait_for_aps(atomic_t *val, int target, int total_delay,
+			int delay_step)
+{
+	int timeout = 0;
+	int delayed = 0;
+
+	while (atomic_read(val) != target) {
+		udelay(delay_step);
+		delayed += delay_step;
+		if (delayed >= total_delay) {
+			timeout = 1;
+			break;
+		}
+	}
+
+	return timeout;
+}
+
+static void ap_do_flight_plan(struct udevice *cpu)
+{
+	int i;
+
+	for (i = 0; i < mp_info.num_records; i++) {
+		struct mp_flight_record *rec = &mp_info.records[i];
+
+		atomic_inc(&rec->cpus_entered);
+		barrier_wait(&rec->barrier);
+
+		if (rec->ap_call != NULL)
+			rec->ap_call(cpu, rec->ap_arg);
+	}
+}
+
+static int find_cpu_by_apid_id(int apic_id, struct udevice **devp)
+{
+	struct udevice *dev;
+
+	*devp = NULL;
+	for (uclass_find_first_device(UCLASS_CPU, &dev);
+	     dev;
+	     uclass_find_next_device(&dev)) {
+		struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+
+		if (plat->cpu_id == apic_id) {
+			*devp = dev;
+			return 0;
+		}
+	}
+
+	return -ENOENT;
+}
+
+/*
+ * By the time APs call ap_init() caching has been setup, and microcode has
+ * been loaded
+ */
+static void ap_init(unsigned int cpu_index)
+{
+	struct udevice *dev;
+	int apic_id;
+	int ret;
+
+	/* Ensure the local apic is enabled */
+	enable_lapic();
+
+	apic_id = lapicid();
+	ret = find_cpu_by_apid_id(apic_id, &dev);
+	if (ret) {
+		debug("Unknown CPU apic_id %x\n", apic_id);
+		goto done;
+	}
+
+	debug("AP: slot %d apic_id %x, dev %s\n", cpu_index, apic_id,
+	      dev ? dev->name : "(apic_id not found)");
+
+	/* Walk the flight plan */
+	ap_do_flight_plan(dev);
+
+	/* Park the AP */
+	debug("parking\n");
+done:
+	stop_this_cpu();
+}
+
+static const unsigned int fixed_mtrrs[NUM_FIXED_MTRRS] = {
+	MTRR_FIX_64K_00000_MSR, MTRR_FIX_16K_80000_MSR, MTRR_FIX_16K_A0000_MSR,
+	MTRR_FIX_4K_C0000_MSR, MTRR_FIX_4K_C8000_MSR, MTRR_FIX_4K_D0000_MSR,
+	MTRR_FIX_4K_D8000_MSR, MTRR_FIX_4K_E0000_MSR, MTRR_FIX_4K_E8000_MSR,
+	MTRR_FIX_4K_F0000_MSR, MTRR_FIX_4K_F8000_MSR,
+};
+
+static inline struct saved_msr *save_msr(int index, struct saved_msr *entry)
+{
+	msr_t msr;
+
+	msr = msr_read(index);
+	entry->index = index;
+	entry->lo = msr.lo;
+	entry->hi = msr.hi;
+
+	/* Return the next entry */
+	entry++;
+	return entry;
+}
+
+static int save_bsp_msrs(char *start, int size)
+{
+	int msr_count;
+	int num_var_mtrrs;
+	struct saved_msr *msr_entry;
+	int i;
+	msr_t msr;
+
+	/* Determine number of MTRRs need to be saved */
+	msr = msr_read(MTRR_CAP_MSR);
+	num_var_mtrrs = msr.lo & 0xff;
+
+	/* 2 * num_var_mtrrs for base and mask. +1 for IA32_MTRR_DEF_TYPE */
+	msr_count = 2 * num_var_mtrrs + NUM_FIXED_MTRRS + 1;
+
+	if ((msr_count * sizeof(struct saved_msr)) > size) {
+		printf("Cannot mirror all %d msrs.\n", msr_count);
+		return -ENOSPC;
+	}
+
+	msr_entry = (void *)start;
+	for (i = 0; i < NUM_FIXED_MTRRS; i++)
+		msr_entry = save_msr(fixed_mtrrs[i], msr_entry);
+
+	for (i = 0; i < num_var_mtrrs; i++) {
+		msr_entry = save_msr(MTRR_PHYS_BASE_MSR(i), msr_entry);
+		msr_entry = save_msr(MTRR_PHYS_MASK_MSR(i), msr_entry);
+	}
+
+	msr_entry = save_msr(MTRR_DEF_TYPE_MSR, msr_entry);
+
+	return msr_count;
+}
+
+static int load_sipi_vector(atomic_t **ap_countp)
+{
+	struct sipi_params_16bit *params16;
+	struct sipi_params *params;
+	static char msr_save[512];
+	char *stack;
+	ulong addr;
+	int code_len;
+	int size;
+	int ret;
+
+	/* Copy in the code */
+	code_len = ap_start16_code_end - ap_start16;
+	debug("Copying SIPI code to %x: %d bytes\n", AP_DEFAULT_BASE,
+	      code_len);
+	memcpy((void *)AP_DEFAULT_BASE, ap_start16, code_len);
+
+	addr = AP_DEFAULT_BASE + (ulong)sipi_params_16bit - (ulong)ap_start16;
+	params16 = (struct sipi_params_16bit *)addr;
+	params16->ap_start = (uint32_t)ap_start;
+	params16->gdt = (uint32_t)gd->arch.gdt;
+	params16->gdt_limit = X86_GDT_SIZE - 1;
+	debug("gdt = %x, gdt_limit = %x\n", params16->gdt, params16->gdt_limit);
+
+	params = (struct sipi_params *)sipi_params;
+	debug("SIPI 32-bit params at %p\n", params);
+	params->idt_ptr = (uint32_t)x86_get_idt();
+
+	params->stack_size = CONFIG_AP_STACK_SIZE;
+	size = params->stack_size * CONFIG_MAX_CPUS;
+	stack = memalign(size, 4096);
+	if (!stack)
+		return -ENOMEM;
+	params->stack_top = (u32)(stack + size);
+
+	params->microcode_ptr = 0;
+	params->msr_table_ptr = (u32)msr_save;
+	ret = save_bsp_msrs(msr_save, sizeof(msr_save));
+	if (ret < 0)
+		return ret;
+	params->msr_count = ret;
+
+	params->c_handler = (uint32_t)&ap_init;
+
+	*ap_countp = &params->ap_count;
+	atomic_set(*ap_countp, 0);
+	debug("SIPI vector is ready\n");
+
+	return 0;
+}
+
+static int check_cpu_devices(int expected_cpus)
+{
+	int i;
+
+	for (i = 0; i < expected_cpus; i++) {
+		struct udevice *dev;
+		int ret;
+
+		ret = uclass_find_device(UCLASS_CPU, i, &dev);
+		if (ret) {
+			debug("Cannot find CPU %d in device tree\n", i);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Returns 1 for timeout. 0 on success */
+static int apic_wait_timeout(int total_delay, int delay_step)
+{
+	int total = 0;
+	int timeout = 0;
+
+	while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY) {
+		udelay(delay_step);
+		total += delay_step;
+		if (total >= total_delay) {
+			timeout = 1;
+			break;
+		}
+	}
+
+	return timeout;
+}
+
+static int start_aps(int ap_count, atomic_t *num_aps)
+{
+	int sipi_vector;
+	/* Max location is 4KiB below 1MiB */
+	const int max_vector_loc = ((1 << 20) - (1 << 12)) >> 12;
+
+	if (ap_count == 0)
+		return 0;
+
+	/* The vector is sent as a 4k aligned address in one byte */
+	sipi_vector = AP_DEFAULT_BASE >> 12;
+
+	if (sipi_vector > max_vector_loc) {
+		printf("SIPI vector too large! 0x%08x\n",
+		       sipi_vector);
+		return -1;
+	}
+
+	debug("Attempting to start %d APs\n", ap_count);
+
+	if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
+		debug("Waiting for ICR not to be busy...");
+		if (apic_wait_timeout(1000, 50)) {
+			debug("timed out. Aborting.\n");
+			return -1;
+		} else {
+			debug("done.\n");
+		}
+	}
+
+	/* Send INIT IPI to all but self */
+	lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+	lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+			   LAPIC_DM_INIT);
+	debug("Waiting for 10ms after sending INIT.\n");
+	mdelay(10);
+
+	/* Send 1st SIPI */
+	if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
+		debug("Waiting for ICR not to be busy...");
+		if (apic_wait_timeout(1000, 50)) {
+			debug("timed out. Aborting.\n");
+			return -1;
+		} else {
+			debug("done.\n");
+		}
+	}
+
+	lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+	lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+			   LAPIC_DM_STARTUP | sipi_vector);
+	debug("Waiting for 1st SIPI to complete...");
+	if (apic_wait_timeout(10000, 50)) {
+		debug("timed out.\n");
+		return -1;
+	} else {
+		debug("done.\n");
+	}
+
+	/* Wait for CPUs to check in up to 200 us */
+	wait_for_aps(num_aps, ap_count, 200, 15);
+
+	/* Send 2nd SIPI */
+	if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
+		debug("Waiting for ICR not to be busy...");
+		if (apic_wait_timeout(1000, 50)) {
+			debug("timed out. Aborting.\n");
+			return -1;
+		} else {
+			debug("done.\n");
+		}
+	}
+
+	lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+	lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
+			   LAPIC_DM_STARTUP | sipi_vector);
+	debug("Waiting for 2nd SIPI to complete...");
+	if (apic_wait_timeout(10000, 50)) {
+		debug("timed out.\n");
+		return -1;
+	} else {
+		debug("done.\n");
+	}
+
+	/* Wait for CPUs to check in */
+	if (wait_for_aps(num_aps, ap_count, 10000, 50)) {
+		debug("Not all APs checked in: %d/%d.\n",
+		      atomic_read(num_aps), ap_count);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int bsp_do_flight_plan(struct udevice *cpu, struct mp_params *mp_params)
+{
+	int i;
+	int ret = 0;
+	const int timeout_us = 100000;
+	const int step_us = 100;
+	int num_aps = mp_params->num_cpus - 1;
+
+	for (i = 0; i < mp_params->num_records; i++) {
+		struct mp_flight_record *rec = &mp_params->flight_plan[i];
+
+		/* Wait for APs if the record is not released */
+		if (atomic_read(&rec->barrier) == 0) {
+			/* Wait for the APs to check in */
+			if (wait_for_aps(&rec->cpus_entered, num_aps,
+					 timeout_us, step_us)) {
+				debug("MP record %d timeout.\n", i);
+				ret = -1;
+			}
+		}
+
+		if (rec->bsp_call != NULL)
+			rec->bsp_call(cpu, rec->bsp_arg);
+
+		release_barrier(&rec->barrier);
+	}
+	return ret;
+}
+
+static int init_bsp(struct udevice **devp)
+{
+	char processor_name[CPU_MAX_NAME_LEN];
+	int apic_id;
+	int ret;
+
+	cpu_get_name(processor_name);
+	debug("CPU: %s.\n", processor_name);
+
+	enable_lapic();
+
+	apic_id = lapicid();
+	ret = find_cpu_by_apid_id(apic_id, devp);
+	if (ret) {
+		printf("Cannot find boot CPU, APIC ID %d\n", apic_id);
+		return ret;
+	}
+
+	return 0;
+}
+
+int mp_init(struct mp_params *p)
+{
+	int num_aps;
+	atomic_t *ap_count;
+	struct udevice *cpu;
+	int ret;
+
+	/* This will cause the CPUs devices to be bound */
+	struct uclass *uc;
+	ret = uclass_get(UCLASS_CPU, &uc);
+	if (ret)
+		return ret;
+
+	ret = init_bsp(&cpu);
+	if (ret) {
+		debug("Cannot init boot CPU: err=%d\n", ret);
+		return ret;
+	}
+
+	if (p == NULL || p->flight_plan == NULL || p->num_records < 1) {
+		printf("Invalid MP parameters\n");
+		return -1;
+	}
+
+	ret = check_cpu_devices(p->num_cpus);
+	if (ret)
+		debug("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n");
+
+	/* Copy needed parameters so that APs have a reference to the plan */
+	mp_info.num_records = p->num_records;
+	mp_info.records = p->flight_plan;
+
+	/* Load the SIPI vector */
+	ret = load_sipi_vector(&ap_count);
+	if (ap_count == NULL)
+		return -1;
+
+	/*
+	 * Make sure SIPI data hits RAM so the APs that come up will see
+	 * the startup code even if the caches are disabled
+	 */
+	wbinvd();
+
+	/* Start the APs providing number of APs and the cpus_entered field */
+	num_aps = p->num_cpus - 1;
+	ret = start_aps(num_aps, ap_count);
+	if (ret) {
+		mdelay(1000);
+		debug("%d/%d eventually checked in?\n", atomic_read(ap_count),
+		      num_aps);
+		return ret;
+	}
+
+	/* Walk the flight plan for the BSP */
+	ret = bsp_do_flight_plan(cpu, p);
+	if (ret) {
+		debug("CPU init failed: err=%d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int mp_init_cpu(struct udevice *cpu, void *unused)
+{
+	return device_probe(cpu);
+}
diff --git a/arch/x86/cpu/sipi_vector.S b/arch/x86/cpu/sipi_vector.S
new file mode 100644
index 0000000..bcef12c
--- /dev/null
+++ b/arch/x86/cpu/sipi_vector.S
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ *
+ * Taken from coreboot file of the same name
+ */
+
+/*
+ * The SIPI vector is responsible for initializing the APs in the sytem. It
+ * loads microcode, sets up MSRs, and enables caching before calling into
+ * C code
+ */
+
+#include <asm/global_data.h>
+#include <asm/msr-index.h>
+#include <asm/processor.h>
+#include <asm/processor-flags.h>
+#include <asm/sipi.h>
+
+#define CODE_SEG	(X86_GDT_ENTRY_32BIT_CS * X86_GDT_ENTRY_SIZE)
+#define DATA_SEG	(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE)
+
+/*
+ * First we have the 16-bit section. Every AP process starts here.
+ * The simple task is to load U-Boot's Global Descriptor Table (GDT) to allow
+ * U-Boot's 32-bit code to become visible, then jump to ap_start.
+ *
+ * Note that this code is copied to RAM below 1MB in mp_init.c, and runs from
+ * there, but the 32-bit code (ap_start and onwards) is part of U-Boot and
+ * is therefore relocated to the top of RAM with other U-Boot code. This
+ * means that for the 16-bit code we must write relocatable code, but for the
+ * rest, we can do what we like.
+ */
+.text
+.code16
+.globl ap_start16
+ap_start16:
+	cli
+	xorl	%eax, %eax
+	movl	%eax, %cr3		/* Invalidate TLB */
+
+	/* setup the data segment */
+	movw	%cs, %ax
+	movw	%ax, %ds
+
+	/* Use an address relative to the data segment for the GDT */
+	movl	$gdtaddr, %ebx
+	subl	$ap_start16, %ebx
+
+	data32 lgdt (%ebx)
+
+	movl	%cr0, %eax
+	andl	$(~(X86_CR0_PG | X86_CR0_AM | X86_CR0_WP | X86_CR0_NE | \
+		    X86_CR0_TS | X86_CR0_EM | X86_CR0_MP)), %eax
+	orl	$(X86_CR0_NW | X86_CR0_CD | X86_CR0_PE), %eax
+	movl	%eax, %cr0
+
+	movl	$ap_start_jmp, %eax
+	subl	$ap_start16, %eax
+	movw	%ax, %bp
+
+	/* Jump to ap_start within U-Boot */
+data32 cs	ljmp	*(%bp)
+
+	.align	4
+.globl sipi_params_16bit
+sipi_params_16bit:
+	/* 48-bit far pointer */
+ap_start_jmp:
+	.long	0		/* offset set to ap_start by U-Boot */
+	.word	CODE_SEG	/* segment */
+
+	.word	0		/* padding */
+gdtaddr:
+	.word	0 /* limit */
+	.long	0 /* table */
+	.word	0 /* unused */
+
+.globl ap_start16_code_end
+ap_start16_code_end:
+
+/*
+ * Set up the special 'fs' segment for global_data. Then jump to ap_continue
+ * to set up the AP.
+ */
+.globl ap_start
+ap_start:
+	.code32
+	movw	$DATA_SEG, %ax
+	movw	%ax, %ds
+	movw	%ax, %es
+	movw	%ax, %ss
+	movw	%ax, %gs
+
+	movw	$(X86_GDT_ENTRY_32BIT_FS * X86_GDT_ENTRY_SIZE), %ax
+	movw	%ax, %fs
+
+	/* Load the Interrupt descriptor table */
+	mov	idt_ptr, %ebx
+	lidt	(%ebx)
+
+	/* Obtain cpu number */
+	movl	ap_count, %eax
+1:
+	movl	%eax, %ecx
+	inc	%ecx
+	lock cmpxchg %ecx, ap_count
+	jnz	1b
+
+	/* Setup stacks for each CPU */
+	movl	stack_size, %eax
+	mul	%ecx
+	movl	stack_top, %edx
+	subl	%eax, %edx
+	mov	%edx, %esp
+	/* Save cpu number */
+	mov	%ecx, %esi
+
+	/* Determine if one should check microcode versions */
+	mov	microcode_ptr, %edi
+	test	%edi, %edi
+	jz	microcode_done /* Bypass if no microde exists */
+
+	/* Get the Microcode version */
+	mov	$1, %eax
+	cpuid
+	mov	$MSR_IA32_UCODE_REV, %ecx
+	rdmsr
+	/* If something already loaded skip loading again */
+	test	%edx, %edx
+	jnz	microcode_done
+
+	/* Determine if parallel microcode loading is allowed */
+	cmp	$0xffffffff, microcode_lock
+	je	load_microcode
+
+	/* Protect microcode loading */
+lock_microcode:
+	lock bts $0, microcode_lock
+	jc	lock_microcode
+
+load_microcode:
+	/* Load new microcode */
+	mov	$MSR_IA32_UCODE_WRITE, %ecx
+	xor	%edx, %edx
+	mov	%edi, %eax
+	/*
+	 * The microcode pointer is passed in pointing to the header. Adjust
+	 * pointer to reflect the payload (header size is 48 bytes)
+	 */
+	add	$UCODE_HEADER_LEN, %eax
+	pusha
+	wrmsr
+	popa
+
+	/* Unconditionally unlock microcode loading */
+	cmp	$0xffffffff, microcode_lock
+	je	microcode_done
+
+	xor	%eax, %eax
+	mov	%eax, microcode_lock
+
+microcode_done:
+	/*
+	 * Load MSRs. Each entry in the table consists of:
+	 * 0: index,
+	 * 4: value[31:0]
+	 * 8: value[63:32]
+	 * See struct saved_msr in mp_init.c.
+	 */
+	mov	msr_table_ptr, %edi
+	mov	msr_count, %ebx
+	test	%ebx, %ebx
+	jz	1f
+load_msr:
+	mov	(%edi), %ecx
+	mov	4(%edi), %eax
+	mov	8(%edi), %edx
+	wrmsr
+	add	$12, %edi
+	dec	%ebx
+	jnz	load_msr
+
+1:
+	/* Enable caching */
+	mov	%cr0, %eax
+	andl	$(~(X86_CR0_CD | X86_CR0_NW)), %eax
+	mov	%eax, %cr0
+
+	/* c_handler(cpu_num) */
+	movl	%esi, %eax	/* cpu_num */
+	mov	c_handler, %eax
+	call	*%eax
+
+	.align	4
+.globl	sipi_params
+sipi_params:
+idt_ptr:
+	.long 0
+stack_top:
+	.long 0
+stack_size:
+	.long 0
+microcode_lock:
+	.long 0
+microcode_ptr:
+	.long 0
+msr_table_ptr:
+	.long 0
+msr_count:
+	.long 0
+c_handler:
+	.long 0
+ap_count:
+	.long 0
diff --git a/arch/x86/include/asm/arch-ivybridge/microcode.h b/arch/x86/include/asm/arch-ivybridge/microcode.h
index b868283..67f32cc 100644
--- a/arch/x86/include/asm/arch-ivybridge/microcode.h
+++ b/arch/x86/include/asm/arch-ivybridge/microcode.h
@@ -7,9 +7,6 @@
 #ifndef __ASM_ARCH_MICROCODE_H
 #define __ASM_ARCH_MICROCODE_H
 
-/* Length of the public header on Intel microcode blobs */
-#define UCODE_HEADER_LEN	0x30
-
 #ifndef __ASSEMBLY__
 
 /**
diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h
new file mode 100644
index 0000000..c0930fd
--- /dev/null
+++ b/arch/x86/include/asm/mp.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ *
+ * Taken from coreboot file of the same name
+ */
+
+#ifndef _X86_MP_H_
+#define _X86_MP_H_
+
+#include <asm/atomic.h>
+
+typedef int (*mp_callback_t)(struct udevice *cpu, void *arg);
+
+/*
+ * A mp_flight_record details a sequence of calls for the APs to perform
+ * along with the BSP to coordinate sequencing. Each flight record either
+ * provides a barrier for each AP before calling the callback or the APs
+ * are allowed to perform the callback without waiting. Regardless, each
+ * record has the cpus_entered field incremented for each record. When
+ * the BSP observes that the cpus_entered matches the number of APs
+ * the bsp_call is called with bsp_arg and upon returning releases the
+ * barrier allowing the APs to make further progress.
+ *
+ * Note that ap_call() and bsp_call() can be NULL. In the NULL case the
+ * callback will just not be called.
+ */
+struct mp_flight_record {
+	atomic_t barrier;
+	atomic_t cpus_entered;
+	mp_callback_t ap_call;
+	void *ap_arg;
+	mp_callback_t bsp_call;
+	void *bsp_arg;
+} __attribute__((aligned(ARCH_DMA_MINALIGN)));
+
+#define MP_FLIGHT_RECORD(barrier_, ap_func_, ap_arg_, bsp_func_, bsp_arg_) \
+	{							\
+		.barrier = ATOMIC_INIT(barrier_),		\
+		.cpus_entered = ATOMIC_INIT(0),			\
+		.ap_call = ap_func_,				\
+		.ap_arg = ap_arg_,				\
+		.bsp_call = bsp_func_,				\
+		.bsp_arg = bsp_arg_,				\
+	}
+
+#define MP_FR_BLOCK_APS(ap_func, ap_arg, bsp_func, bsp_arg) \
+	MP_FLIGHT_RECORD(0, ap_func, ap_arg, bsp_func, bsp_arg)
+
+#define MP_FR_NOBLOCK_APS(ap_func, ap_arg, bsp_func, bsp_arg) \
+	MP_FLIGHT_RECORD(1, ap_func, ap_arg, bsp_func, bsp_arg)
+
+/*
+ * The mp_params structure provides the arguments to the mp subsystem
+ * for bringing up APs.
+ *
+ * At present this is overkill for U-Boot, but it may make it easier to add
+ * SMM support.
+ */
+struct mp_params {
+	int num_cpus; /* Total cpus include BSP */
+	int parallel_microcode_load;
+	const void *microcode_pointer;
+	/* Flight plan  for APs and BSP */
+	struct mp_flight_record *flight_plan;
+	int num_records;
+};
+
+/*
+ * mp_init() will set up the SIPI vector and bring up the APs according to
+ * mp_params. Each flight record will be executed according to the plan. Note
+ * that the MP infrastructure uses SMM default area without saving it. It's
+ * up to the chipset or mainboard to either e820 reserve this area or save this
+ * region prior to calling mp_init() and restoring it after mp_init returns.
+ *
+ * At the time mp_init() is called the MTRR MSRs are mirrored into APs then
+ * caching is enabled before running the flight plan.
+ *
+ * The MP init has the following properties:
+ * 1. APs are brought up in parallel.
+ * 2. The ordering of cpu number and APIC ids is not deterministic.
+ *    Therefore, one cannot rely on this property or the order of devices in
+ *    the device tree unless the chipset or mainboard know the APIC ids
+ *    a priori.
+ *
+ * mp_init() returns < 0 on error, 0 on success.
+ */
+int mp_init(struct mp_params *params);
+
+/* Probes the CPU device */
+int mp_init_cpu(struct udevice *cpu, void *unused);
+
+#endif /* _X86_MP_H_ */
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 3841593..3ad617c 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -34,8 +34,10 @@
 /* Number of MTRRs supported */
 #define MTRR_COUNT		8
 
-#define NUM_FIXED_RANGES 88
-#define RANGES_PER_FIXED_MTRR 8
+#define NUM_FIXED_MTRRS		11
+#define RANGES_PER_FIXED_MTRR	8
+#define NUM_FIXED_RANGES	(NUM_FIXED_MTRRS * RANGES_PER_FIXED_MTRR)
+
 #define MTRR_FIX_64K_00000_MSR 0x250
 #define MTRR_FIX_16K_80000_MSR 0x258
 #define MTRR_FIX_16K_A0000_MSR 0x259
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 3575d34..7c77b90 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -23,6 +23,9 @@
 
 #define X86_GDT_SIZE		(X86_GDT_NUM_ENTRIES * X86_GDT_ENTRY_SIZE)
 
+/* Length of the public header on Intel microcode blobs */
+#define UCODE_HEADER_LEN	0x30
+
 #ifndef __ASSEMBLY__
 
 /*
diff --git a/arch/x86/include/asm/sipi.h b/arch/x86/include/asm/sipi.h
new file mode 100644
index 0000000..25d7d31
--- /dev/null
+++ b/arch/x86/include/asm/sipi.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015 Gooogle, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _ASM_SIPI_H
+#define _ASM_SIPI_H
+
+#define AP_DEFAULT_BASE 0x30000
+#define AP_DEFAULT_SIZE 0x10000
+
+#ifndef __ASSEMBLER__
+
+/**
+ * struct sipi_params_16bit - 16-bit SIPI entry-point parameters
+ *
+ * These are set up in the same space as the SIPI 16-bit code so that each AP
+ * can access the parameters when it boots.
+ *
+ * Each of these must be set up for the AP to boot, except @segment which is
+ * set in the assembly code.
+ *
+ * @ap_start:		32-bit SIPI entry point for U-Boot
+ * @segment:		Code segment for U-Boot
+ * @pad:		Padding (not used)
+ * @gdt_limit:		U-Boot GDT limit (X86_GDT_SIZE - 1)
+ * @gdt:		U-Boot GDT (gd->arch.gdt)
+ * @unused:		Not used
+ */
+struct __packed sipi_params_16bit {
+	u32 ap_start;
+	u16 segment;
+	u16 pad;
+	u16 gdt_limit;
+	u32 gdt;
+	u16 unused;
+};
+
+/**
+ * struct sipi_params - 32-bit SIP entry-point parameters
+ *
+ * These are used by the AP init code and must be set up before the APs start.
+ *
+ * The stack area extends down from @stack_top, with @stack_size allocated
+ * for each AP.
+ *
+ * @idt_ptr:		Interrupt descriptor table pointer
+ * @stack_top:		Top of the AP stack area
+ * @stack_size:		Size of each AP's stack
+ * @microcode_lock:	Used to ensure only one AP loads microcode at once
+ *			0xffffffff enables parallel loading.
+ * @microcode_ptr:	Pointer to microcode, or 0 if none
+ * @msr_table_ptr:	Pointer to saved MSRs, a list of struct saved_msr
+ * @msr_count:		Number of saved MSRs
+ * @c_handler:		C function to call once early init is complete
+ * @ap_count:		Shared atomic value to allocate CPU indexes
+ */
+struct sipi_params {
+	u32 idt_ptr;
+	u32 stack_top;
+	u32 stack_size;
+	u32 microcode_lock;
+	u32 microcode_ptr;
+	u32 msr_table_ptr;
+	u32 msr_count;
+	u32 c_handler;
+	atomic_t ap_count;
+};
+
+/* 16-bit AP entry point */
+void ap_start16(void);
+
+/* end of 16-bit code/data, marks the region to be copied to SIP vector */
+void ap_start16_code_end(void);
+
+/* 32-bit AP entry point */
+void ap_start(void);
+
+extern char sipi_params_16bit[];
+extern char sipi_params[];
+
+#endif /* __ASSEMBLER__ */
+
+#endif
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 2/5] x86: Add functions to set and clear bits on MSRs
  2015-04-30  4:25 [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support for Minnowboard MAX Simon Glass
  2015-04-30  4:25 ` [U-Boot] [PATCH v3 1/5] x86: Add multi-processor init Simon Glass
@ 2015-04-30  4:26 ` Simon Glass
  2015-04-30  6:11   ` Bin Meng
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 3/5] x86: Allow CPUs to be set up after relocation Simon Glass
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: Simon Glass @ 2015-04-30  4:26 UTC (permalink / raw)
  To: u-boot

Since we do these sorts of operations a lot, it is useful to have a simpler
API, similar to clrsetbits_le32().

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add msr_clrbits_64() too

Changes in v2: None

 arch/x86/include/asm/msr.h | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 1955a75..c480920 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -128,6 +128,34 @@ static inline void wrmsr(unsigned msr, unsigned low, unsigned high)
 #define wrmsrl(msr, val)						\
 	native_write_msr((msr), (u32)((u64)(val)), (u32)((u64)(val) >> 32))
 
+static inline void msr_clrsetbits_64(unsigned msr, u64 clear, u64 set)
+{
+	u64 val;
+
+	val = native_read_msr(msr);
+	val &= ~clear;
+	val |= set;
+	wrmsrl(msr, val);
+}
+
+static inline void msr_setbits_64(unsigned msr, u64 set)
+{
+	u64 val;
+
+	val = native_read_msr(msr);
+	val |= set;
+	wrmsrl(msr, val);
+}
+
+static inline void msr_clrbits_64(unsigned msr, u64 clear)
+{
+	u64 val;
+
+	val = native_read_msr(msr);
+	val &= ~clear;
+	wrmsrl(msr, val);
+}
+
 /* rdmsr with exception handling */
 #define rdmsr_safe(msr, p1, p2)					\
 ({								\
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 3/5] x86: Allow CPUs to be set up after relocation
  2015-04-30  4:25 [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support for Minnowboard MAX Simon Glass
  2015-04-30  4:25 ` [U-Boot] [PATCH v3 1/5] x86: Add multi-processor init Simon Glass
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 2/5] x86: Add functions to set and clear bits on MSRs Simon Glass
@ 2015-04-30  4:26 ` Simon Glass
  2015-04-30  6:14   ` Bin Meng
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 4/5] x86: Add a CPU driver for baytrail Simon Glass
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: Simon Glass @ 2015-04-30  4:26 UTC (permalink / raw)
  To: u-boot

This permits init of additional CPU cores after relocation and when driver
model is ready.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2:
- Correct 'I2C uclass' typo
- Add blank line in x86_cpu_get_desc()

 arch/x86/cpu/cpu.c                | 38 ++++++++++++++++++++++++++++++++++++++
 arch/x86/include/asm/cpu.h        | 14 ++++++++++++++
 arch/x86/include/asm/u-boot-x86.h |  2 ++
 common/board_r.c                  |  2 +-
 4 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
index 78eb3fe..bb4a110 100644
--- a/arch/x86/cpu/cpu.c
+++ b/arch/x86/cpu/cpu.c
@@ -21,6 +21,8 @@
 
 #include <common.h>
 #include <command.h>
+#include <cpu.h>
+#include <dm.h>
 #include <errno.h>
 #include <malloc.h>
 #include <asm/control_regs.h>
@@ -518,6 +520,16 @@ char *cpu_get_name(char *name)
 	return ptr;
 }
 
+int x86_cpu_get_desc(struct udevice *dev, char *buf, int size)
+{
+	if (size < CPU_MAX_NAME_LEN)
+		return -ENOSPC;
+
+	cpu_get_name(buf);
+
+	return 0;
+}
+
 int default_print_cpuinfo(void)
 {
 	printf("CPU: %s, vendor %s, device %xh\n",
@@ -600,3 +612,29 @@ int last_stage_init(void)
 	return 0;
 }
 #endif
+
+__weak int x86_init_cpus(void)
+{
+	return 0;
+}
+
+int cpu_init_r(void)
+{
+	return x86_init_cpus();
+}
+
+static const struct cpu_ops cpu_x86_ops = {
+	.get_desc	= x86_cpu_get_desc,
+};
+
+static const struct udevice_id cpu_x86_ids[] = {
+	{ .compatible = "cpu-x86" },
+	{ }
+};
+
+U_BOOT_DRIVER(cpu_x86_drv) = {
+	.name		= "cpu_x86",
+	.id		= UCLASS_CPU,
+	.of_match	= cpu_x86_ids,
+	.ops		= &cpu_x86_ops,
+};
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 08284ee..ebc74ad 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -197,6 +197,20 @@ const char *cpu_vendor_name(int vendor);
 char *cpu_get_name(char *name);
 
 /**
+ *
+* x86_cpu_get_desc() - Get a description string for an x86 CPU
+*
+* This uses cpu_get_name() and is suitable to use as the get_desc() method for
+* the CPU uclass.
+*
+* @dev:		Device to check (UCLASS_CPU)
+* @buf:		Buffer to place string
+* @size:	Size of string space
+* @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+*/
+int x86_cpu_get_desc(struct udevice *dev, char *buf, int size);
+
+/**
  * cpu_call64() - Jump to a 64-bit Linux kernel (internal function)
  *
  * The kernel is uncompressed and the 64-bit entry point is expected to be
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
index 122e054..be103c0 100644
--- a/arch/x86/include/asm/u-boot-x86.h
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -69,6 +69,8 @@ uint64_t timer_get_tsc(void);
 
 void quick_ram_check(void);
 
+int x86_init_cpus(void);
+
 #define PCI_VGA_RAM_IMAGE_START		0xc0000
 
 #endif	/* _U_BOOT_I386_H_ */
diff --git a/common/board_r.c b/common/board_r.c
index 307124e..1a46f62 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -779,7 +779,7 @@ init_fnc_t init_sequence_r[] = {
 	initr_flash,
 #endif
 	INIT_FUNC_WATCHDOG_RESET
-#if defined(CONFIG_PPC) || defined(CONFIG_M68K)
+#if defined(CONFIG_PPC) || defined(CONFIG_M68K) || defined(CONFIG_X86)
 	/* initialize higher level parts of CPU like time base and timers */
 	cpu_init_r,
 #endif
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 4/5] x86: Add a CPU driver for baytrail
  2015-04-30  4:25 [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support for Minnowboard MAX Simon Glass
                   ` (2 preceding siblings ...)
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 3/5] x86: Allow CPUs to be set up after relocation Simon Glass
@ 2015-04-30  4:26 ` Simon Glass
  2015-04-30  6:26   ` Bin Meng
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 5/5] x86: Enable multi-core init for Minnowboard MAX Simon Glass
  2015-04-30  5:11 ` [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support " Simon Glass
  5 siblings, 1 reply; 18+ messages in thread
From: Simon Glass @ 2015-04-30  4:26 UTC (permalink / raw)
  To: u-boot

This driver supports multi-core init and sets up the CPU frequencies
correctly.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Collect all new MSRs into msr-index.h
- Spell 'BayTrail' like so
- Make set_max_freq() static

Changes in v2: None

 arch/x86/cpu/baytrail/Makefile                    |   1 +
 arch/x86/cpu/baytrail/cpu.c                       | 205 ++++++++++++++++++++++
 arch/x86/include/asm/arch-ivybridge/model_206ax.h |   2 -
 arch/x86/include/asm/msr-index.h                  |  22 ++-
 arch/x86/include/asm/turbo.h                      |   3 -
 5 files changed, 227 insertions(+), 6 deletions(-)
 create mode 100644 arch/x86/cpu/baytrail/cpu.c

diff --git a/arch/x86/cpu/baytrail/Makefile b/arch/x86/cpu/baytrail/Makefile
index 8914e8b..c78b644 100644
--- a/arch/x86/cpu/baytrail/Makefile
+++ b/arch/x86/cpu/baytrail/Makefile
@@ -4,6 +4,7 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
+obj-y += cpu.o
 obj-y += early_uart.o
 obj-y += fsp_configs.o
 obj-y += pci.o
diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
new file mode 100644
index 0000000..1d48206
--- /dev/null
+++ b/arch/x86/cpu/baytrail/cpu.c
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ *
+ * Based on code from coreboot
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <asm/cpu.h>
+#include <asm/lapic.h>
+#include <asm/mp.h>
+#include <asm/msr.h>
+#include <asm/turbo.h>
+
+#ifdef CONFIG_SMP
+static int enable_smis(struct udevice *cpu, void *unused)
+{
+	return 0;
+}
+
+static struct mp_flight_record mp_steps[] = {
+	MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
+	/* Wait for APs to finish initialization before proceeding. */
+	MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
+};
+
+static int detect_num_cpus(void)
+{
+	int ecx = 0;
+
+	/*
+	 * Use the algorithm described in Intel 64 and IA-32 Architectures
+	 * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
+	 * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
+	 * of CPUID Extended Topology Leaf.
+	 */
+	while (1) {
+		struct cpuid_result leaf_b;
+
+		leaf_b = cpuid_ext(0xb, ecx);
+
+		/*
+		 * Bay Trail doesn't have hyperthreading so just determine the
+		 * number of cores by from level type (ecx[15:8] == * 2)
+		 */
+		if ((leaf_b.ecx & 0xff00) == 0x0200)
+			return leaf_b.ebx & 0xffff;
+		ecx++;
+	}
+}
+
+static int baytrail_init_cpus(void)
+{
+	struct mp_params mp_params;
+
+	lapic_setup();
+
+	mp_params.num_cpus = detect_num_cpus();
+	mp_params.parallel_microcode_load = 0,
+	mp_params.flight_plan = &mp_steps[0];
+	mp_params.num_records = ARRAY_SIZE(mp_steps);
+	mp_params.microcode_pointer = 0;
+
+	if (mp_init(&mp_params)) {
+		printf("Warning: MP init failure\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+#endif
+
+int x86_init_cpus(void)
+{
+#ifdef CONFIG_SMP
+	debug("Init additional CPUs\n");
+	baytrail_init_cpus();
+#endif
+
+	return 0;
+}
+
+static void set_max_freq(void)
+{
+	msr_t perf_ctl;
+	msr_t msr;
+
+	/* Enable speed step */
+	msr = msr_read(MSR_IA32_MISC_ENABLES);
+	msr.lo |= (1 << 16);
+	msr_write(MSR_IA32_MISC_ENABLES, msr);
+
+	/*
+	 * Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of
+	 * the PERF_CTL
+	 */
+	msr = msr_read(MSR_IACORE_RATIOS);
+	perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
+
+	/*
+	 * Set guaranteed vid [21:16] from IACORE_VIDS to bits [7:0] of
+	 * the PERF_CTL
+	 */
+	msr = msr_read(MSR_IACORE_VIDS);
+	perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16;
+	perf_ctl.hi = 0;
+
+	msr_write(MSR_IA32_PERF_CTL, perf_ctl);
+}
+
+static int cpu_x86_baytrail_probe(struct udevice *dev)
+{
+	debug("Init BayTrail core\n");
+
+	/*
+	 * On BayTrail the turbo disable bit is actually scoped at the
+	 * building-block level, not package. For non-BSP cores that are
+	 * within a building block, enable turbo. The cores within the BSP's
+	 * building block will just see it already enabled and move on.
+	 */
+	if (lapicid())
+		turbo_enable();
+
+	/* Dynamic L2 shrink enable and threshold */
+	msr_clrsetbits_64(MSR_PMG_CST_CONFIG_CONTROL, 0x3f000f, 0xe0008),
+
+	/* Disable C1E */
+	msr_clrsetbits_64(MSR_POWER_CTL, 2, 0);
+	msr_setbits_64(MSR_POWER_MISC, 0x44);
+
+	/* Set this core to max frequency ratio */
+	set_max_freq();
+
+	return 0;
+}
+
+static unsigned bus_freq(void)
+{
+	msr_t clk_info = msr_read(MSR_BSEL_CR_OVERCLOCK_CONTROL);
+	switch (clk_info.lo & 0x3) {
+	case 0:
+		return 83333333;
+	case 1:
+		return 100000000;
+	case 2:
+		return 133333333;
+	case 3:
+		return 116666666;
+	default:
+		return 0;
+	}
+}
+
+static unsigned long tsc_freq(void)
+{
+	msr_t platform_info;
+	ulong bclk = bus_freq();
+
+	if (!bclk)
+		return 0;
+
+	platform_info = msr_read(MSR_PLATFORM_INFO);
+
+	return bclk * ((platform_info.lo >> 8) & 0xff);
+}
+
+static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
+{
+	info->cpu_freq = tsc_freq();
+	info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU;
+
+	return 0;
+}
+
+static int cpu_x86_baytrail_bind(struct udevice *dev)
+{
+	struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+
+	plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+				      "intel,apic-id", -1);
+
+	return 0;
+}
+
+static const struct cpu_ops cpu_x86_baytrail_ops = {
+	.get_desc	= x86_cpu_get_desc,
+	.get_info	= baytrail_get_info,
+};
+
+static const struct udevice_id cpu_x86_baytrail_ids[] = {
+	{ .compatible = "intel,baytrail-cpu" },
+	{ }
+};
+
+U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
+	.name		= "cpu_x86_baytrail",
+	.id		= UCLASS_CPU,
+	.of_match	= cpu_x86_baytrail_ids,
+	.bind		= cpu_x86_baytrail_bind,
+	.probe		= cpu_x86_baytrail_probe,
+	.ops		= &cpu_x86_baytrail_ops,
+};
diff --git a/arch/x86/include/asm/arch-ivybridge/model_206ax.h b/arch/x86/include/asm/arch-ivybridge/model_206ax.h
index 7b4f2e7..d2f9006 100644
--- a/arch/x86/include/asm/arch-ivybridge/model_206ax.h
+++ b/arch/x86/include/asm/arch-ivybridge/model_206ax.h
@@ -37,7 +37,6 @@
 #define MSR_MISC_PWR_MGMT		0x1aa
 #define  MISC_PWR_MGMT_EIST_HW_DIS	(1 << 0)
 #define MSR_TURBO_RATIO_LIMIT		0x1ad
-#define MSR_POWER_CTL			0x1fc
 
 #define MSR_PKGC3_IRTL			0x60a
 #define MSR_PKGC6_IRTL			0x60b
@@ -63,7 +62,6 @@
 #define MSR_PP1_CURRENT_CONFIG		0x602
 #define  PP1_CURRENT_LIMIT_SNB		(35 << 3) /* 35 A */
 #define  PP1_CURRENT_LIMIT_IVB		(50 << 3) /* 50 A */
-#define MSR_PKG_POWER_SKU_UNIT		0x606
 #define MSR_PKG_POWER_SKU		0x614
 
 #define IVB_CONFIG_TDP_MIN_CPUID	0x306a2
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 2cbb270..38dbb31 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -53,10 +53,17 @@
 #define SNB_C1_AUTO_UNDEMOTE		(1UL << 27)
 #define SNB_C3_AUTO_UNDEMOTE		(1UL << 28)
 
+#define MSR_BSEL_CR_OVERCLOCK_CONTROL	0x000000cd
 #define MSR_PLATFORM_INFO		0x000000ce
+#define MSR_PMG_CST_CONFIG_CONTROL	0x000000e2
+#define SINGLE_PCTL			(1 << 11)
+
 #define MSR_MTRRcap			0x000000fe
 #define MSR_IA32_BBL_CR_CTL		0x00000119
 #define MSR_IA32_BBL_CR_CTL3		0x0000011e
+#define MSR_POWER_MISC			0x00000120
+#define ENABLE_ULFM_AUTOCM_MASK		(1 << 2)
+#define ENABLE_INDP_AUTOCM_MASK		(1 << 3)
 
 #define MSR_IA32_SYSENTER_CS		0x00000174
 #define MSR_IA32_SYSENTER_ESP		0x00000175
@@ -66,6 +73,7 @@
 #define MSR_IA32_MCG_STATUS		0x0000017a
 #define MSR_IA32_MCG_CTL		0x0000017b
 
+#define MSR_IA32_MISC_ENABLES		0x000001a0
 #define MSR_OFFCORE_RSP_0		0x000001a6
 #define MSR_OFFCORE_RSP_1		0x000001a7
 #define MSR_NHM_TURBO_RATIO_LIMIT	0x000001ad
@@ -73,6 +81,7 @@
 
 #define MSR_LBR_SELECT			0x000001c8
 #define MSR_LBR_TOS			0x000001c9
+#define MSR_POWER_CTL			0x000001fc
 #define MSR_LBR_NHM_FROM		0x00000680
 #define MSR_LBR_NHM_TO			0x000006c0
 #define MSR_LBR_CORE_FROM		0x00000040
@@ -136,7 +145,7 @@
 
 /* Run Time Average Power Limiting (RAPL) Interface */
 
-#define MSR_RAPL_POWER_UNIT		0x00000606
+#define MSR_PKG_POWER_SKU_UNIT		0x00000606
 
 #define MSR_PKG_POWER_LIMIT		0x00000610
 #define MSR_PKG_ENERGY_STATUS		0x00000611
@@ -158,6 +167,16 @@
 #define MSR_PP1_POLICY			0x00000642
 
 #define MSR_CORE_C1_RES			0x00000660
+#define MSR_IACORE_RATIOS		0x0000066a
+#define MSR_IACORE_TURBO_RATIOS		0x0000066c
+#define MSR_IACORE_VIDS			0x0000066b
+#define MSR_IACORE_TURBO_VIDS		0x0000066d
+#define MSR_PKG_TURBO_CFG1		0x00000670
+#define MSR_CPU_TURBO_WKLD_CFG1		0x00000671
+#define MSR_CPU_TURBO_WKLD_CFG2		0x00000672
+#define MSR_CPU_THERM_CFG1		0x00000673
+#define MSR_CPU_THERM_CFG2		0x00000674
+#define MSR_CPU_THERM_SENS_CFG		0x00000675
 
 #define MSR_AMD64_MC0_MASK		0xc0010044
 
@@ -348,6 +367,7 @@
 #define MSR_THERM2_CTL_TM_SELECT	(1ULL << 16)
 
 #define MSR_IA32_MISC_ENABLE		0x000001a0
+#define H_MISC_DISABLE_TURBO		(1 << 6)
 
 #define MSR_IA32_TEMPERATURE_TARGET	0x000001a2
 
diff --git a/arch/x86/include/asm/turbo.h b/arch/x86/include/asm/turbo.h
index bb0d4b4..21b910b 100644
--- a/arch/x86/include/asm/turbo.h
+++ b/arch/x86/include/asm/turbo.h
@@ -12,9 +12,6 @@
 #define CPUID_LEAF_PM		6
 #define PM_CAP_TURBO_MODE	(1 << 1)
 
-#define MSR_IA32_MISC_ENABLES	0x1a0
-#define H_MISC_DISABLE_TURBO	(1 << 6)
-
 enum {
 	TURBO_UNKNOWN,
 	TURBO_UNAVAILABLE,
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 5/5] x86: Enable multi-core init for Minnowboard MAX
  2015-04-30  4:25 [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support for Minnowboard MAX Simon Glass
                   ` (3 preceding siblings ...)
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 4/5] x86: Add a CPU driver for baytrail Simon Glass
@ 2015-04-30  4:26 ` Simon Glass
  2015-05-01  0:52   ` Simon Glass
  2015-04-30  5:11 ` [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support " Simon Glass
  5 siblings, 1 reply; 18+ messages in thread
From: Simon Glass @ 2015-04-30  4:26 UTC (permalink / raw)
  To: u-boot

Enable the CPU uclass and Simple Firmware interface for Minnowbaord MAX. This
enables multi-core support in Linux.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
---

Changes in v3: None
Changes in v2: None

 arch/x86/dts/minnowmax.dts  | 20 ++++++++++++++++++++
 configs/minnowmax_defconfig |  4 ++++
 2 files changed, 24 insertions(+)

diff --git a/arch/x86/dts/minnowmax.dts b/arch/x86/dts/minnowmax.dts
index 0233f61..7103bc5 100644
--- a/arch/x86/dts/minnowmax.dts
+++ b/arch/x86/dts/minnowmax.dts
@@ -68,6 +68,26 @@
 		stdout-path = "/serial";
 	};
 
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			device_type = "cpu";
+			compatible = "intel,baytrail-cpu";
+			reg = <0>;
+			intel,apic-id = <0>;
+		};
+
+		cpu at 1 {
+			device_type = "cpu";
+			compatible = "intel,baytrail-cpu";
+			reg = <1>;
+			intel,apic-id = <4>;
+		};
+
+	};
+
 	spi {
 		#address-cells = <1>;
 		#size-cells = <0>;
diff --git a/configs/minnowmax_defconfig b/configs/minnowmax_defconfig
index c59f4ac..426fb52 100644
--- a/configs/minnowmax_defconfig
+++ b/configs/minnowmax_defconfig
@@ -8,3 +8,7 @@ CONFIG_FRAMEBUFFER_SET_VESA_MODE=y
 CONFIG_FRAMEBUFFER_VESA_MODE_11A=y
 CONFIG_MMCONF_BASE_ADDRESS=0xe0000000
 CONFIG_HAVE_INTEL_ME=y
+CONFIG_GENERATE_SFI_TABLE=y
+CONFIG_CPU=y
+CONFIG_CMD_CPU=y
+CONFIG_SMP=y
-- 
2.2.0.rc0.207.ga3a616c

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support for Minnowboard MAX
  2015-04-30  4:25 [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support for Minnowboard MAX Simon Glass
                   ` (4 preceding siblings ...)
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 5/5] x86: Enable multi-core init for Minnowboard MAX Simon Glass
@ 2015-04-30  5:11 ` Simon Glass
  2015-04-30  6:16   ` Bin Meng
  5 siblings, 1 reply; 18+ messages in thread
From: Simon Glass @ 2015-04-30  5:11 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On 29 Apr 2015 10:26 pm, "Simon Glass" <sjg@chromium.org> wrote:
>
> This series adds a new CPU uclass which is intended to be useful on any
> architecture. So far it has a very simple interface and a command to show
> CPU details.
>
> This series also introduces multi-core init for x86. It is implemented and
> enabled on Minnowboard MAX, a single/dual-core Atom board. The CPU uclass
is
> implemented for x86 and the Simple Firmware Interface provides these
details
> to the kernel, since ACPI is not yet available.
>
> With these changes Minnowboard MAX can boot into Linux with both cores
> enabled.
>
> This series is available at u-boot-x86 branch 'cpu-working'.
>
> Changes in v3:
> - Rename CONFIG_STACK_SIZE to CONFIG_AP_STACK_SIZE
> - Remove sipi_vector_location and sipi_vector_location_size variables
> - Remove annoying /* 1ms */ comments
> - Rename sipi.S to sipi_vector.S
> - Correct 'ap_start32' to 'ap_start'
> - Use macros for cr0 bit fields
> - Correct style in a multi-line comment
> - Use UCODE_HEADER_LEN instead of 48
> - Remove unnecessary underscores in MP_FR_BLOCK_APS and MP_FR_NOBLOCK_APS
> - Use 'cpu number' instead of 'coreboot cpu number'
> - Remove a stray blank line in sipi.h
> - Enhance comment for @microcode_lock
> - Rename SMM_DEFAULT_BASE/SIZE to AP_DEFAULT_BASE/SIZE and drop smm.h
> - Use data32 instead of our own 'o32'
> - Move NUM_FIXED_MTRRS to mtrr.h
> - Avoid using asmlinkage on ap_init()
> - Add msr_clrbits_64() too
> - Collect all new MSRs into msr-index.h
> - Spell 'BayTrail' like so
> - Make set_max_freq() static

I did not sort out the secondary CPU init in this series. I will take a
look.

>
> Changes in v2:
> - Correct 'I2C uclass' typo
> - Add blank line in x86_cpu_get_desc()
>
> Simon Glass (5):
>   x86: Add multi-processor init
>   x86: Add functions to set and clear bits on MSRs
>   x86: Allow CPUs to be set up after relocation
>   x86: Add a CPU driver for baytrail
>   x86: Enable multi-core init for Minnowboard MAX
>
>  arch/x86/Kconfig                                  |  30 ++
>  arch/x86/cpu/Makefile                             |   2 +
>  arch/x86/cpu/baytrail/Makefile                    |   1 +
>  arch/x86/cpu/baytrail/cpu.c                       | 205 +++++++++
>  arch/x86/cpu/cpu.c                                |  38 ++
>  arch/x86/cpu/ivybridge/car.S                      |   1 +
>  arch/x86/cpu/ivybridge/model_206ax.c              |   4 +-
>  arch/x86/cpu/mp_init.c                            | 496
++++++++++++++++++++++
>  arch/x86/cpu/sipi_vector.S                        | 216 ++++++++++
>  arch/x86/dts/minnowmax.dts                        |  20 +
>  arch/x86/include/asm/arch-ivybridge/microcode.h   |   3 -
>  arch/x86/include/asm/arch-ivybridge/model_206ax.h |   2 -
>  arch/x86/include/asm/cpu.h                        |  14 +
>  arch/x86/include/asm/mp.h                         |  94 ++++
>  arch/x86/include/asm/msr-index.h                  |  22 +-
>  arch/x86/include/asm/msr.h                        |  28 ++
>  arch/x86/include/asm/mtrr.h                       |   6 +-
>  arch/x86/include/asm/processor.h                  |   3 +
>  arch/x86/include/asm/sipi.h                       |  86 ++++
>  arch/x86/include/asm/turbo.h                      |   3 -
>  arch/x86/include/asm/u-boot-x86.h                 |   2 +
>  common/board_r.c                                  |   2 +-
>  configs/minnowmax_defconfig                       |   4 +
>  23 files changed, 1268 insertions(+), 14 deletions(-)
>  create mode 100644 arch/x86/cpu/baytrail/cpu.c
>  create mode 100644 arch/x86/cpu/mp_init.c
>  create mode 100644 arch/x86/cpu/sipi_vector.S
>  create mode 100644 arch/x86/include/asm/mp.h
>  create mode 100644 arch/x86/include/asm/sipi.h
>
> --
> 2.2.0.rc0.207.ga3a616c
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 1/5] x86: Add multi-processor init
  2015-04-30  4:25 ` [U-Boot] [PATCH v3 1/5] x86: Add multi-processor init Simon Glass
@ 2015-04-30  6:09   ` Bin Meng
  2015-05-01  0:52     ` Simon Glass
  0 siblings, 1 reply; 18+ messages in thread
From: Bin Meng @ 2015-04-30  6:09 UTC (permalink / raw)
  To: u-boot

On Thu, Apr 30, 2015 at 12:25 PM, Simon Glass <sjg@chromium.org> wrote:
> Most modern x86 CPUs include more than one CPU core. The OS normally requires
> that these 'Application Processors' (APs) be brought up by the boot loader.
> Add the required support to U-Boot to init additional APs.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

> Changes in v3:
> - Rename CONFIG_STACK_SIZE to CONFIG_AP_STACK_SIZE
> - Remove sipi_vector_location and sipi_vector_location_size variables
> - Remove annoying /* 1ms */ comments
> - Rename sipi.S to sipi_vector.S
> - Correct 'ap_start32' to 'ap_start'
> - Use macros for cr0 bit fields
> - Correct style in a multi-line comment
> - Use UCODE_HEADER_LEN instead of 48
> - Remove unnecessary underscores in MP_FR_BLOCK_APS and MP_FR_NOBLOCK_APS
> - Use 'cpu number' instead of 'coreboot cpu number'
> - Remove a stray blank line in sipi.h
> - Enhance comment for @microcode_lock
> - Rename SMM_DEFAULT_BASE/SIZE to AP_DEFAULT_BASE/SIZE and drop smm.h
> - Use data32 instead of our own 'o32'
> - Move NUM_FIXED_MTRRS to mtrr.h
> - Avoid using asmlinkage on ap_init()
>

[snip]

Regards,
Bin

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 2/5] x86: Add functions to set and clear bits on MSRs
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 2/5] x86: Add functions to set and clear bits on MSRs Simon Glass
@ 2015-04-30  6:11   ` Bin Meng
  2015-05-01  0:52     ` Simon Glass
  0 siblings, 1 reply; 18+ messages in thread
From: Bin Meng @ 2015-04-30  6:11 UTC (permalink / raw)
  To: u-boot

On Thu, Apr 30, 2015 at 12:26 PM, Simon Glass <sjg@chromium.org> wrote:
> Since we do these sorts of operations a lot, it is useful to have a simpler
> API, similar to clrsetbits_le32().
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Add msr_clrbits_64() too

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

[snip]

Regards,
Bin

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 3/5] x86: Allow CPUs to be set up after relocation
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 3/5] x86: Allow CPUs to be set up after relocation Simon Glass
@ 2015-04-30  6:14   ` Bin Meng
  2015-05-01  0:52     ` Simon Glass
  0 siblings, 1 reply; 18+ messages in thread
From: Bin Meng @ 2015-04-30  6:14 UTC (permalink / raw)
  To: u-boot

On Thu, Apr 30, 2015 at 12:26 PM, Simon Glass <sjg@chromium.org> wrote:
> This permits init of additional CPU cores after relocation and when driver
> model is ready.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3: None
> Changes in v2:
> - Correct 'I2C uclass' typo
> - Add blank line in x86_cpu_get_desc()

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

[snip]

Regards,
Bin

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support for Minnowboard MAX
  2015-04-30  5:11 ` [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support " Simon Glass
@ 2015-04-30  6:16   ` Bin Meng
  2015-04-30 18:22     ` Simon Glass
  0 siblings, 1 reply; 18+ messages in thread
From: Bin Meng @ 2015-04-30  6:16 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Thu, Apr 30, 2015 at 1:11 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Bin,
>
> On 29 Apr 2015 10:26 pm, "Simon Glass" <sjg@chromium.org> wrote:
>>
>> This series adds a new CPU uclass which is intended to be useful on any
>> architecture. So far it has a very simple interface and a command to show
>> CPU details.
>>
>> This series also introduces multi-core init for x86. It is implemented and
>> enabled on Minnowboard MAX, a single/dual-core Atom board. The CPU uclass
>> is
>> implemented for x86 and the Simple Firmware Interface provides these
>> details
>> to the kernel, since ACPI is not yet available.
>>
>> With these changes Minnowboard MAX can boot into Linux with both cores
>> enabled.
>>
>> This series is available at u-boot-x86 branch 'cpu-working'.
>>
>> Changes in v3:
>> - Rename CONFIG_STACK_SIZE to CONFIG_AP_STACK_SIZE
>> - Remove sipi_vector_location and sipi_vector_location_size variables
>> - Remove annoying /* 1ms */ comments
>> - Rename sipi.S to sipi_vector.S
>> - Correct 'ap_start32' to 'ap_start'
>> - Use macros for cr0 bit fields
>> - Correct style in a multi-line comment
>> - Use UCODE_HEADER_LEN instead of 48
>> - Remove unnecessary underscores in MP_FR_BLOCK_APS and MP_FR_NOBLOCK_APS
>> - Use 'cpu number' instead of 'coreboot cpu number'
>> - Remove a stray blank line in sipi.h
>> - Enhance comment for @microcode_lock
>> - Rename SMM_DEFAULT_BASE/SIZE to AP_DEFAULT_BASE/SIZE and drop smm.h
>> - Use data32 instead of our own 'o32'
>> - Move NUM_FIXED_MTRRS to mtrr.h
>> - Avoid using asmlinkage on ap_init()
>> - Add msr_clrbits_64() too
>> - Collect all new MSRs into msr-index.h
>> - Spell 'BayTrail' like so
>> - Make set_max_freq() static
>
> I did not sort out the secondary CPU init in this series. I will take a
> look.
>

Thanks. What about the LAPIC patch? Is it dropped?
http://patchwork.ozlabs.org/patch/465854/

[snip]

Regards,
Bin

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 4/5] x86: Add a CPU driver for baytrail
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 4/5] x86: Add a CPU driver for baytrail Simon Glass
@ 2015-04-30  6:26   ` Bin Meng
  2015-05-01  0:52     ` Simon Glass
  0 siblings, 1 reply; 18+ messages in thread
From: Bin Meng @ 2015-04-30  6:26 UTC (permalink / raw)
  To: u-boot

On Thu, Apr 30, 2015 at 12:26 PM, Simon Glass <sjg@chromium.org> wrote:
> This driver supports multi-core init and sets up the CPU frequencies
> correctly.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Collect all new MSRs into msr-index.h
> - Spell 'BayTrail' like so
> - Make set_max_freq() static
>

Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

[snip]

Regards,
Bin

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support for Minnowboard MAX
  2015-04-30  6:16   ` Bin Meng
@ 2015-04-30 18:22     ` Simon Glass
  0 siblings, 0 replies; 18+ messages in thread
From: Simon Glass @ 2015-04-30 18:22 UTC (permalink / raw)
  To: u-boot

Hi Bin,

On 30 April 2015 at 00:16, Bin Meng <bmeng.cn@gmail.com> wrote:
> Hi Simon,
>
> On Thu, Apr 30, 2015 at 1:11 PM, Simon Glass <sjg@chromium.org> wrote:
>> Hi Bin,
>>
>> On 29 Apr 2015 10:26 pm, "Simon Glass" <sjg@chromium.org> wrote:
>>>
>>> This series adds a new CPU uclass which is intended to be useful on any
>>> architecture. So far it has a very simple interface and a command to show
>>> CPU details.
>>>
>>> This series also introduces multi-core init for x86. It is implemented and
>>> enabled on Minnowboard MAX, a single/dual-core Atom board. The CPU uclass
>>> is
>>> implemented for x86 and the Simple Firmware Interface provides these
>>> details
>>> to the kernel, since ACPI is not yet available.
>>>
>>> With these changes Minnowboard MAX can boot into Linux with both cores
>>> enabled.
>>>
>>> This series is available at u-boot-x86 branch 'cpu-working'.
>>>
>>> Changes in v3:
>>> - Rename CONFIG_STACK_SIZE to CONFIG_AP_STACK_SIZE
>>> - Remove sipi_vector_location and sipi_vector_location_size variables
>>> - Remove annoying /* 1ms */ comments
>>> - Rename sipi.S to sipi_vector.S
>>> - Correct 'ap_start32' to 'ap_start'
>>> - Use macros for cr0 bit fields
>>> - Correct style in a multi-line comment
>>> - Use UCODE_HEADER_LEN instead of 48
>>> - Remove unnecessary underscores in MP_FR_BLOCK_APS and MP_FR_NOBLOCK_APS
>>> - Use 'cpu number' instead of 'coreboot cpu number'
>>> - Remove a stray blank line in sipi.h
>>> - Enhance comment for @microcode_lock
>>> - Rename SMM_DEFAULT_BASE/SIZE to AP_DEFAULT_BASE/SIZE and drop smm.h
>>> - Use data32 instead of our own 'o32'
>>> - Move NUM_FIXED_MTRRS to mtrr.h
>>> - Avoid using asmlinkage on ap_init()
>>> - Add msr_clrbits_64() too
>>> - Collect all new MSRs into msr-index.h
>>> - Spell 'BayTrail' like so
>>> - Make set_max_freq() static
>>
>> I did not sort out the secondary CPU init in this series. I will take a
>> look.
>>
>
> Thanks. What about the LAPIC patch? Is it dropped?
> http://patchwork.ozlabs.org/patch/465854/

Yes, that was a clean-up patch so not required. As you noticed I did
not go far enough so I'll take another crack at it later.

Regards,
Simon

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 1/5] x86: Add multi-processor init
  2015-04-30  6:09   ` Bin Meng
@ 2015-05-01  0:52     ` Simon Glass
  0 siblings, 0 replies; 18+ messages in thread
From: Simon Glass @ 2015-05-01  0:52 UTC (permalink / raw)
  To: u-boot

On 30 April 2015 at 00:09, Bin Meng <bmeng.cn@gmail.com> wrote:
> On Thu, Apr 30, 2015 at 12:25 PM, Simon Glass <sjg@chromium.org> wrote:
>> Most modern x86 CPUs include more than one CPU core. The OS normally requires
>> that these 'Application Processors' (APs) be brought up by the boot loader.
>> Add the required support to U-Boot to init additional APs.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Applied to u-boot-x86.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 2/5] x86: Add functions to set and clear bits on MSRs
  2015-04-30  6:11   ` Bin Meng
@ 2015-05-01  0:52     ` Simon Glass
  0 siblings, 0 replies; 18+ messages in thread
From: Simon Glass @ 2015-05-01  0:52 UTC (permalink / raw)
  To: u-boot

On 30 April 2015 at 00:11, Bin Meng <bmeng.cn@gmail.com> wrote:
> On Thu, Apr 30, 2015 at 12:26 PM, Simon Glass <sjg@chromium.org> wrote:
>> Since we do these sorts of operations a lot, it is useful to have a simpler
>> API, similar to clrsetbits_le32().
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>> Changes in v3:
>> - Add msr_clrbits_64() too
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Applied to u-boot-x86.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 3/5] x86: Allow CPUs to be set up after relocation
  2015-04-30  6:14   ` Bin Meng
@ 2015-05-01  0:52     ` Simon Glass
  0 siblings, 0 replies; 18+ messages in thread
From: Simon Glass @ 2015-05-01  0:52 UTC (permalink / raw)
  To: u-boot

On 30 April 2015 at 00:14, Bin Meng <bmeng.cn@gmail.com> wrote:
> On Thu, Apr 30, 2015 at 12:26 PM, Simon Glass <sjg@chromium.org> wrote:
>> This permits init of additional CPU cores after relocation and when driver
>> model is ready.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>> Changes in v3: None
>> Changes in v2:
>> - Correct 'I2C uclass' typo
>> - Add blank line in x86_cpu_get_desc()
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Applied to u-boot-x86.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 4/5] x86: Add a CPU driver for baytrail
  2015-04-30  6:26   ` Bin Meng
@ 2015-05-01  0:52     ` Simon Glass
  0 siblings, 0 replies; 18+ messages in thread
From: Simon Glass @ 2015-05-01  0:52 UTC (permalink / raw)
  To: u-boot

On 30 April 2015 at 00:26, Bin Meng <bmeng.cn@gmail.com> wrote:
> On Thu, Apr 30, 2015 at 12:26 PM, Simon Glass <sjg@chromium.org> wrote:
>> This driver supports multi-core init and sets up the CPU frequencies
>> correctly.
>>
>> Signed-off-by: Simon Glass <sjg@chromium.org>
>> ---
>>
>> Changes in v3:
>> - Collect all new MSRs into msr-index.h
>> - Spell 'BayTrail' like so
>> - Make set_max_freq() static
>>
>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Applied to u-boot-x86.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH v3 5/5] x86: Enable multi-core init for Minnowboard MAX
  2015-04-30  4:26 ` [U-Boot] [PATCH v3 5/5] x86: Enable multi-core init for Minnowboard MAX Simon Glass
@ 2015-05-01  0:52   ` Simon Glass
  0 siblings, 0 replies; 18+ messages in thread
From: Simon Glass @ 2015-05-01  0:52 UTC (permalink / raw)
  To: u-boot

On 29 April 2015 at 22:26, Simon Glass <sjg@chromium.org> wrote:
> Enable the CPU uclass and Simple Firmware interface for Minnowbaord MAX. This
> enables multi-core support in Linux.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>

Applied to u-boot-x86.

> ---
>
> Changes in v3: None
> Changes in v2: None
>
>  arch/x86/dts/minnowmax.dts  | 20 ++++++++++++++++++++
>  configs/minnowmax_defconfig |  4 ++++
>  2 files changed, 24 insertions(+)

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2015-05-01  0:52 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-30  4:25 [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support for Minnowboard MAX Simon Glass
2015-04-30  4:25 ` [U-Boot] [PATCH v3 1/5] x86: Add multi-processor init Simon Glass
2015-04-30  6:09   ` Bin Meng
2015-05-01  0:52     ` Simon Glass
2015-04-30  4:26 ` [U-Boot] [PATCH v3 2/5] x86: Add functions to set and clear bits on MSRs Simon Glass
2015-04-30  6:11   ` Bin Meng
2015-05-01  0:52     ` Simon Glass
2015-04-30  4:26 ` [U-Boot] [PATCH v3 3/5] x86: Allow CPUs to be set up after relocation Simon Glass
2015-04-30  6:14   ` Bin Meng
2015-05-01  0:52     ` Simon Glass
2015-04-30  4:26 ` [U-Boot] [PATCH v3 4/5] x86: Add a CPU driver for baytrail Simon Glass
2015-04-30  6:26   ` Bin Meng
2015-05-01  0:52     ` Simon Glass
2015-04-30  4:26 ` [U-Boot] [PATCH v3 5/5] x86: Enable multi-core init for Minnowboard MAX Simon Glass
2015-05-01  0:52   ` Simon Glass
2015-04-30  5:11 ` [U-Boot] [PATCH v3 0/5] x86: Add CPU uclass and multi-core support " Simon Glass
2015-04-30  6:16   ` Bin Meng
2015-04-30 18:22     ` Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.