<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>