<p>Subrata Banik has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/25621">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">cpu/x86: Create mp_init_by_apic_id() function to perform single AP init<br><br>This function provides an option to perform initialization of single<br>AP based on APIC id.<br><br>Modify associated mp init APIs to accept APIC ID as input. If APIC<br>ID is 0 then enable all associated APs else just enable the specific AP<br>which is marked by APIC ID.<br><br>BRANCH=none<br>BUG=b:74436746<br>TEST=Able to perform single AP init based on given APIC ID.<br><br>Change-Id: I1bc19a19ef442214d784905806b6172558d1e5ca<br>Signed-off-by: Subrata Banik <subrata.banik@intel.com><br>---<br>M src/cpu/x86/mp_init.c<br>M src/include/cpu/x86/mp.h<br>2 files changed, 113 insertions(+), 11 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/21/25621/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c</span><br><span>index 6d1ae26..52feca9 100644</span><br><span>--- a/src/cpu/x86/mp_init.c</span><br><span>+++ b/src/cpu/x86/mp_init.c</span><br><span>@@ -391,11 +391,11 @@</span><br><span> return ap_count;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int allocate_cpu_devices(struct bus *cpu_bus, struct mp_params *p)</span><br><span style="color: hsl(120, 100%, 40%);">+static int allocate_cpu_devices(struct bus *cpu_bus, struct mp_params *p,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t apic_id)</span><br><span> {</span><br><span> int i;</span><br><span> int max_cpus;</span><br><span style="color: hsl(0, 100%, 40%);">- struct cpu_info *info;</span><br><span> </span><br><span> max_cpus = p->num_cpus;</span><br><span> if (max_cpus > CONFIG_MAX_CPUS) {</span><br><span>@@ -404,7 +404,6 @@</span><br><span> max_cpus = CONFIG_MAX_CPUS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- info = cpu_info();</span><br><span> for (i = 1; i < max_cpus; i++) {</span><br><span> struct device_path cpu_path;</span><br><span> struct device *new;</span><br><span>@@ -414,7 +413,7 @@</span><br><span> </span><br><span> /* Assuming linear APIC space allocation. AP will set its own</span><br><span> APIC id in the ap_init() path above. */</span><br><span style="color: hsl(0, 100%, 40%);">- cpu_path.apic.apic_id = info->cpu->path.apic.apic_id + i;</span><br><span style="color: hsl(120, 100%, 40%);">+ cpu_path.apic.apic_id = apic_id + i;</span><br><span> </span><br><span> /* Allocate the new CPU device structure */</span><br><span> new = alloc_find_dev(cpu_bus, &cpu_path);</span><br><span>@@ -446,7 +445,8 @@</span><br><span> return timeout;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_aps)</span><br><span style="color: hsl(120, 100%, 40%);">+static int start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_aps,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t apic_id)</span><br><span> {</span><br><span> int sipi_vector;</span><br><span> /* Max location is 4KiB below 1MiB */</span><br><span>@@ -464,7 +464,10 @@</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- printk(BIOS_DEBUG, "Attempting to start %d APs\n", ap_count);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!apic_id)</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "Attempting to start %d APs\n", ap_count);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "Attempting to start 1 APs with APIC ID = %d \n", apic_id);</span><br><span> </span><br><span> if ((lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY)) {</span><br><span> printk(BIOS_DEBUG, "Waiting for ICR not to be busy...");</span><br><span>@@ -476,7 +479,7 @@</span><br><span> }</span><br><span> </span><br><span> /* Send INIT IPI to all but self. */</span><br><span style="color: hsl(0, 100%, 40%);">- lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));</span><br><span style="color: hsl(120, 100%, 40%);">+ lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apic_id));</span><br><span> lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |</span><br><span> LAPIC_DM_INIT);</span><br><span> printk(BIOS_DEBUG, "Waiting for 10ms after sending INIT.\n");</span><br><span>@@ -492,7 +495,7 @@</span><br><span> printk(BIOS_DEBUG, "done.\n");</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));</span><br><span style="color: hsl(120, 100%, 40%);">+ lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apic_id));</span><br><span> lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |</span><br><span> LAPIC_DM_STARTUP | sipi_vector);</span><br><span> printk(BIOS_DEBUG, "Waiting for 1st SIPI to complete...");</span><br><span>@@ -515,7 +518,7 @@</span><br><span> printk(BIOS_DEBUG, "done.\n");</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(0));</span><br><span style="color: hsl(120, 100%, 40%);">+ lapic_write_around(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apic_id));</span><br><span> lapic_write_around(LAPIC_ICR, LAPIC_DEST_ALLBUT | LAPIC_INT_ASSERT |</span><br><span> LAPIC_DM_STARTUP | sipi_vector);</span><br><span> printk(BIOS_DEBUG, "Waiting for 2nd SIPI to complete...");</span><br><span>@@ -626,6 +629,8 @@</span><br><span> {</span><br><span> int num_cpus;</span><br><span> atomic_t *ap_count;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct cpu_info *info;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t apic_id;</span><br><span> </span><br><span> init_bsp(cpu_bus);</span><br><span> </span><br><span>@@ -634,8 +639,10 @@</span><br><span> return -1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ info = cpu_info();</span><br><span style="color: hsl(120, 100%, 40%);">+ apic_id = info->cpu->path.apic.apic_id;</span><br><span> /* Default to currently running CPU. */</span><br><span style="color: hsl(0, 100%, 40%);">- num_cpus = allocate_cpu_devices(cpu_bus, p);</span><br><span style="color: hsl(120, 100%, 40%);">+ num_cpus = allocate_cpu_devices(cpu_bus, p, apic_id);</span><br><span> </span><br><span> if (num_cpus < p->num_cpus) {</span><br><span> printk(BIOS_CRIT,</span><br><span>@@ -659,7 +666,8 @@</span><br><span> </span><br><span> /* Start the APs providing number of APs and the cpus_entered field. */</span><br><span> global_num_aps = p->num_cpus - 1;</span><br><span style="color: hsl(0, 100%, 40%);">- if (start_aps(cpu_bus, global_num_aps, ap_count) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (start_aps(cpu_bus, global_num_aps, ap_count, apic_id) < 0) {</span><br><span> mdelay(1000);</span><br><span> printk(BIOS_DEBUG, "%d/%d eventually checked in?\n",</span><br><span> atomic_read(ap_count), global_num_aps);</span><br><span>@@ -670,6 +678,58 @@</span><br><span> return bsp_do_flight_plan(p);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * init_this_ap() will set up the SIPI vector and bring up the APs according to</span><br><span style="color: hsl(120, 100%, 40%);">+ * mp_params. Each flight record will be executed according to the plan.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The MP initialization has the following properties:</span><br><span style="color: hsl(120, 100%, 40%);">+ * 1. AP is brought up from reset.</span><br><span style="color: hsl(120, 100%, 40%);">+ * 2. Init AP is done based on APIC ID, which has been set earlier.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * init_this_ap() returns < 0 on error, 0 on success.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int init_this_ap(struct bus *cpu_bus, struct mp_params *p, int apicid)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int num_cpus;</span><br><span style="color: hsl(120, 100%, 40%);">+ atomic_t *ap_count;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (p == NULL || p->flight_plan == NULL || p->num_records < 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_CRIT, "Invalid MP parameters\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Default to currently running CPU. */</span><br><span style="color: hsl(120, 100%, 40%);">+ num_cpus = allocate_cpu_devices(cpu_bus, p, apicid - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (num_cpus < p->num_cpus) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_CRIT,</span><br><span style="color: hsl(120, 100%, 40%);">+ "ERROR: More cpus requested (%d) than supported (%d).\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ p->num_cpus, num_cpus);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Copy needed parameters so that APs have a reference to the plan. */</span><br><span style="color: hsl(120, 100%, 40%);">+ mp_info.num_records = p->num_records;</span><br><span style="color: hsl(120, 100%, 40%);">+ mp_info.records = p->flight_plan;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Load the SIPI vector. */</span><br><span style="color: hsl(120, 100%, 40%);">+ ap_count = load_sipi_vector(p);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ap_count == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Make sure SIPI data hits RAM so the APs that come up will see</span><br><span style="color: hsl(120, 100%, 40%);">+ * the startup code even if the caches are disabled. */</span><br><span style="color: hsl(120, 100%, 40%);">+ wbinvd();</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (start_aps(cpu_bus, global_num_aps, ap_count, apicid) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ mdelay(1000);</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_DEBUG, "%d/%d eventually checked in?\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ atomic_read(ap_count), global_num_aps);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Calls cpu_initialize(info->index) which calls the coreboot CPU drivers. */</span><br><span> static void mp_initialize_cpu(void)</span><br><span> {</span><br><span>@@ -1064,3 +1124,31 @@</span><br><span> </span><br><span> return ret;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int mp_init_by_apic_id(struct bus *cpu_bus, const struct mp_ops *mp_ops, int apicid)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int ret;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct mp_params mp_params;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(&mp_params, 0, sizeof(mp_params));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (apicid <= 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printk(BIOS_ERR, "Invalid APIC ID: %d\n", apicid);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ mp_params.num_cpus = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Gather microcode information. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (mp_ops->get_microcode_info != NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+ mp_ops->get_microcode_info(&mp_params.microcode_pointer,</span><br><span style="color: hsl(120, 100%, 40%);">+ &mp_params.parallel_microcode_load);</span><br><span style="color: hsl(120, 100%, 40%);">+ mp_params.flight_plan = &mp_steps[0];</span><br><span style="color: hsl(120, 100%, 40%);">+ mp_params.num_records = ARRAY_SIZE(mp_steps);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Start the APs providing number of APs and the cpus_entered field. */</span><br><span style="color: hsl(120, 100%, 40%);">+ global_num_aps = mp_ops->get_cpu_count() - 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ret = init_this_ap(cpu_bus, &mp_params, apicid);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return ret;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/include/cpu/x86/mp.h b/src/include/cpu/x86/mp.h</span><br><span>index bc9cf05..04fba6a 100644</span><br><span>--- a/src/include/cpu/x86/mp.h</span><br><span>+++ b/src/include/cpu/x86/mp.h</span><br><span>@@ -116,6 +116,20 @@</span><br><span> */</span><br><span> int mp_init_with_smm(struct bus *cpu_bus, const struct mp_ops *mp_ops);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * mp_init_by_apic_id() returns < 0 on failure and 0 on success. The mp_ops</span><br><span style="color: hsl(120, 100%, 40%);">+ * argument is used to drive the multiprocess initialization.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The sequence of operations</span><br><span style="color: hsl(120, 100%, 40%);">+ * is the following:</span><br><span style="color: hsl(120, 100%, 40%);">+ * 1. get_cpu_count()</span><br><span style="color: hsl(120, 100%, 40%);">+ * 2. get_microcode_info()</span><br><span style="color: hsl(120, 100%, 40%);">+ * 3. mp_initialize_cpu() for each cpu</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This function to bring back AP into Enable state marked by APIC ID,</span><br><span style="color: hsl(120, 100%, 40%);">+ * if this AP is in disable/halt state before.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int mp_init_by_apic_id(struct bus *cpu_bus, const struct mp_ops *mp_ops,</span><br><span style="color: hsl(120, 100%, 40%);">+ int apicid);</span><br><span> </span><br><span> /*</span><br><span> * After APs are up and PARALLEL_MP_AP_WORK is enabled one can issue work</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/25621">change 25621</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/25621"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I1bc19a19ef442214d784905806b6172558d1e5ca </div>
<div style="display:none"> Gerrit-Change-Number: 25621 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Subrata Banik <subrata.banik@intel.com> </div>