Subrata Banik has uploaded this change for review. ( https://review.coreboot.org/25622
Change subject: cpu/x86: Refactor run_ap_work() function to support no timeout
......................................................................
cpu/x86: Refactor run_ap_work() function to support no timeout
There might be certain requirement in user function where user
might not want to pass any timeout value, in those cases run_ap_work() should
consider infinity as timeout and perform all APs initialization as per specification.
BRANCH=none
BUG=b:74436746
TEST=run_ap_work() is running successfully with 0 expire_us.
Change-Id: Iacd67768c8a120f6a01baaa6817468f6b9a3b764
Signed-off-by: Subrata Banik <subrata.banik(a)intel.com>
---
M src/cpu/x86/mp_init.c
1 file changed, 37 insertions(+), 16 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/22/25622/1
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c
index 52feca9..f1600fd 100644
--- a/src/cpu/x86/mp_init.c
+++ b/src/cpu/x86/mp_init.c
@@ -946,6 +946,24 @@
*(volatile mp_callback_t *)slot = value;
}
+static int execute_callback_on_ap(void)
+{
+ int cpus_accepted;
+ int i;
+ int cur_cpu = cpu_index();
+
+ cpus_accepted = 0;
+
+ for (i = 0; i < ARRAY_SIZE(ap_callbacks); i++) {
+ if (cur_cpu == i)
+ continue;
+ if (read_callback(&ap_callbacks[i]) == NULL)
+ cpus_accepted++;
+ }
+
+ return cpus_accepted;
+}
+
static int run_ap_work(mp_callback_t func, long expire_us)
{
int i;
@@ -966,22 +984,25 @@
}
mfence();
- /* Wait for all the APs to signal back that call has been accepted. */
- stopwatch_init_usecs_expire(&sw, expire_us);
- do {
- cpus_accepted = 0;
-
- for (i = 0; i < ARRAY_SIZE(ap_callbacks); i++) {
- if (cur_cpu == i)
- continue;
- if (read_callback(&ap_callbacks[i]) == NULL)
- cpus_accepted++;
- }
-
- if (cpus_accepted == global_num_aps)
- return 0;
- } while (!stopwatch_expired(&sw));
-
+ if (expire_us) {
+ /*
+ * Wait for all the APs to signal back that call has been
+ * accepted.
+ */
+ stopwatch_init_usecs_expire(&sw, expire_us);
+ do {
+ cpus_accepted = execute_callback_on_ap();
+ if (cpus_accepted == global_num_aps)
+ return 0;
+ } while (!stopwatch_expired(&sw));
+ } else {
+ /* Wait for all the APs to signal back with no timeout */
+ do {
+ cpus_accepted = execute_callback_on_ap();
+ if (cpus_accepted == global_num_aps)
+ return 0;
+ } while (1);
+ }
printk(BIOS_ERR, "AP call expired. %d/%d CPUs accepted.\n",
cpus_accepted, global_num_aps);
return -1;
--
To view, visit https://review.coreboot.org/25622
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: Iacd67768c8a120f6a01baaa6817468f6b9a3b764
Gerrit-Change-Number: 25622
Gerrit-PatchSet: 1
Gerrit-Owner: Subrata Banik <subrata.banik(a)intel.com>
Subrata Banik has uploaded this change for review. ( https://review.coreboot.org/25621
Change subject: cpu/x86: Create mp_init_by_apic_id() function to perform single AP init
......................................................................
cpu/x86: Create mp_init_by_apic_id() function to perform single AP init
This function provides an option to perform initialization of single
AP based on APIC id.
Modify associated mp init APIs to accept APIC ID as input. If APIC
ID is 0 then enable all associated APs else just enable the specific AP
which is marked by APIC ID.
BRANCH=none
BUG=b:74436746
TEST=Able to perform single AP init based on given APIC ID.
Change-Id: I1bc19a19ef442214d784905806b6172558d1e5ca
Signed-off-by: Subrata Banik <subrata.banik(a)intel.com>
---
M src/cpu/x86/mp_init.c
M src/include/cpu/x86/mp.h
2 files changed, 113 insertions(+), 11 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/21/25621/1
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c
index 6d1ae26..52feca9 100644
--- a/src/cpu/x86/mp_init.c
+++ b/src/cpu/x86/mp_init.c
@@ -391,11 +391,11 @@
return ap_count;
}
-static int allocate_cpu_devices(struct bus *cpu_bus, struct mp_params *p)
+static int allocate_cpu_devices(struct bus *cpu_bus, struct mp_params *p,
+ uint8_t apic_id)
{
int i;
int max_cpus;
- struct cpu_info *info;
max_cpus = p->num_cpus;
if (max_cpus > CONFIG_MAX_CPUS) {
@@ -404,7 +404,6 @@
max_cpus = CONFIG_MAX_CPUS;
}
- info = cpu_info();
for (i = 1; i < max_cpus; i++) {
struct device_path cpu_path;
struct device *new;
@@ -414,7 +413,7 @@
/* Assuming linear APIC space allocation. AP will set its own
APIC id in the ap_init() path above. */
- cpu_path.apic.apic_id = info->cpu->path.apic.apic_id + i;
+ cpu_path.apic.apic_id = apic_id + i;
/* Allocate the new CPU device structure */
new = alloc_find_dev(cpu_bus, &cpu_path);
@@ -446,7 +445,8 @@
return timeout;
}
-static int start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_aps)
+static int start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_aps,
+ uint8_t apic_id)
{
int sipi_vector;
/* Max location is 4KiB below 1MiB */
@@ -464,7 +464,10 @@
return -1;
}
- printk(BIOS_DEBUG, "Attempting to start %d APs\n", ap_count);
+ if (!apic_id)
+ printk(BIOS_DEBUG, "Attempting to start %d APs\n", ap_count);
+ else
+ printk(BIOS_DEBUG, "Attempting to start 1 APs with APIC ID = %d \n", apic_id);
if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {
printk(BIOS_DEBUG, "Waiting for ICR not to be busy...");
@@ -476,7 +479,7 @@
}
/* Send INIT IPI to all but self. */
- lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+ lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apic_id));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_INIT);
printk(BIOS_DEBUG, "Waiting for 10ms after sending INIT.\n");
@@ -492,7 +495,7 @@
printk(BIOS_DEBUG, "done.\n");
}
- lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+ lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apic_id));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
printk(BIOS_DEBUG, "Waiting for 1st SIPI to complete...");
@@ -515,7 +518,7 @@
printk(BIOS_DEBUG, "done.\n");
}
- lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));
+ lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apic_id));
lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |
LAPIC_DM_STARTUP | sipi_vector);
printk(BIOS_DEBUG, "Waiting for 2nd SIPI to complete...");
@@ -626,6 +629,8 @@
{
int num_cpus;
atomic_t *ap_count;
+ struct cpu_info *info;
+ uint8_t apic_id;
init_bsp(cpu_bus);
@@ -634,8 +639,10 @@
return -1;
}
+ info = cpu_info();
+ apic_id = info->cpu->path.apic.apic_id;
/* Default to currently running CPU. */
- num_cpus = allocate_cpu_devices(cpu_bus, p);
+ num_cpus = allocate_cpu_devices(cpu_bus, p, apic_id);
if (num_cpus < p->num_cpus) {
printk(BIOS_CRIT,
@@ -659,7 +666,8 @@
/* Start the APs providing number of APs and the cpus_entered field. */
global_num_aps = p->num_cpus - 1;
- if (start_aps(cpu_bus, global_num_aps, ap_count) < 0) {
+
+ if (start_aps(cpu_bus, global_num_aps, ap_count, apic_id) < 0) {
mdelay(1000);
printk(BIOS_DEBUG, "%d/%d eventually checked in?\n",
atomic_read(ap_count), global_num_aps);
@@ -670,6 +678,58 @@
return bsp_do_flight_plan(p);
}
+/*
+ * init_this_ap() 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.
+ *
+ * The MP initialization has the following properties:
+ * 1. AP is brought up from reset.
+ * 2. Init AP is done based on APIC ID, which has been set earlier.
+ *
+ * init_this_ap() returns < 0 on error, 0 on success.
+ */
+static int init_this_ap(struct bus *cpu_bus, struct mp_params *p, int apicid)
+{
+ int num_cpus;
+ atomic_t *ap_count;
+
+ if (p == NULL || p->flight_plan == NULL || p->num_records < 1) {
+ printk(BIOS_CRIT, "Invalid MP parameters\n");
+ return -1;
+ }
+ /* Default to currently running CPU. */
+ num_cpus = allocate_cpu_devices(cpu_bus, p, apicid - 1);
+
+ if (num_cpus < p->num_cpus) {
+ printk(BIOS_CRIT,
+ "ERROR: More cpus requested (%d) than supported (%d).\n",
+ p->num_cpus, num_cpus);
+ return -1;
+ }
+
+ /* 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. */
+ ap_count = load_sipi_vector(p);
+ 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();
+
+ if (start_aps(cpu_bus, global_num_aps, ap_count, apicid) < 0) {
+ mdelay(1000);
+ printk(BIOS_DEBUG, "%d/%d eventually checked in?\n",
+ atomic_read(ap_count), global_num_aps);
+ return -1;
+ }
+
+ return 0;
+}
+
/* Calls cpu_initialize(info->index) which calls the coreboot CPU drivers. */
static void mp_initialize_cpu(void)
{
@@ -1064,3 +1124,31 @@
return ret;
}
+
+int mp_init_by_apic_id(struct bus *cpu_bus, const struct mp_ops *mp_ops, int apicid)
+{
+ int ret;
+ struct mp_params mp_params;
+
+ memset(&mp_params, 0, sizeof(mp_params));
+
+ if (apicid <= 0) {
+ printk(BIOS_ERR, "Invalid APIC ID: %d\n", apicid);
+ return -1;
+ }
+
+ mp_params.num_cpus = 1;
+ /* Gather microcode information. */
+ if (mp_ops->get_microcode_info != NULL)
+ mp_ops->get_microcode_info(&mp_params.microcode_pointer,
+ &mp_params.parallel_microcode_load);
+ mp_params.flight_plan = &mp_steps[0];
+ mp_params.num_records = ARRAY_SIZE(mp_steps);
+
+ /* Start the APs providing number of APs and the cpus_entered field. */
+ global_num_aps = mp_ops->get_cpu_count() - 1;
+
+ ret = init_this_ap(cpu_bus, &mp_params, apicid);
+
+ return ret;
+}
diff --git a/src/include/cpu/x86/mp.h b/src/include/cpu/x86/mp.h
index bc9cf05..04fba6a 100644
--- a/src/include/cpu/x86/mp.h
+++ b/src/include/cpu/x86/mp.h
@@ -116,6 +116,20 @@
*/
int mp_init_with_smm(struct bus *cpu_bus, const struct mp_ops *mp_ops);
+/*
+ * mp_init_by_apic_id() returns < 0 on failure and 0 on success. The mp_ops
+ * argument is used to drive the multiprocess initialization.
+ * The sequence of operations
+ * is the following:
+ * 1. get_cpu_count()
+ * 2. get_microcode_info()
+ * 3. mp_initialize_cpu() for each cpu
+ *
+ * This function to bring back AP into Enable state marked by APIC ID,
+ * if this AP is in disable/halt state before.
+ */
+int mp_init_by_apic_id(struct bus *cpu_bus, const struct mp_ops *mp_ops,
+ int apicid);
/*
* After APs are up and PARALLEL_MP_AP_WORK is enabled one can issue work
--
To view, visit https://review.coreboot.org/25621
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I1bc19a19ef442214d784905806b6172558d1e5ca
Gerrit-Change-Number: 25621
Gerrit-PatchSet: 1
Gerrit-Owner: Subrata Banik <subrata.banik(a)intel.com>
Subrata Banik has uploaded this change for review. ( https://review.coreboot.org/25620
Change subject: cpu/x86: Make mp_get_apic_id() function externally available
......................................................................
cpu/x86: Make mp_get_apic_id() function externally available
This function convert cpu number to repective APIC id.
BUG=b:74436746
BRANCH=none
TEST=mp_get_apic_id() can be accessed from other files now.
Change-Id: I5c5eda8325f941ab84d8a3fe0dae64be71c44855
Signed-off-by: Subrata Banik <subrata.banik(a)intel.com>
---
M src/cpu/x86/mp_init.c
M src/include/cpu/x86/mp.h
2 files changed, 4 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/20/25620/1
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c
index f99abaf..6d1ae26 100644
--- a/src/cpu/x86/mp_init.c
+++ b/src/cpu/x86/mp_init.c
@@ -679,7 +679,7 @@
}
/* Returns APIC id for coreboot CPU number or < 0 on failure. */
-static int mp_get_apic_id(int cpu_slot)
+int mp_get_apic_id(int cpu_slot)
{
if (cpu_slot >= CONFIG_MAX_CPUS || cpu_slot < 0)
return -1;
diff --git a/src/include/cpu/x86/mp.h b/src/include/cpu/x86/mp.h
index f6afc84..bc9cf05 100644
--- a/src/include/cpu/x86/mp.h
+++ b/src/include/cpu/x86/mp.h
@@ -153,4 +153,7 @@
/* Release a barrier so that other CPUs waiting for that barrier can continue */
void release_barrier(atomic_t *b);
+/* Returns APIC id for coreboot CPU number or < 0 on failure. */
+int mp_get_apic_id(int cpu_slot);
+
#endif /* _X86_MP_H_ */
--
To view, visit https://review.coreboot.org/25620
To unsubscribe, or for help writing mail filters, visit https://review.coreboot.org/settings
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I5c5eda8325f941ab84d8a3fe0dae64be71c44855
Gerrit-Change-Number: 25620
Gerrit-PatchSet: 1
Gerrit-Owner: Subrata Banik <subrata.banik(a)intel.com>