Skip to content

Commit aacc6f2

Browse files
krystian-hebelSergiiDmytruk
authored andcommitted
arch/x86/smp: start APs in parallel during boot
Multiple delays are required when sending IPIs and waiting for responses. During boot, 4 such IPIs were sent per each AP. With this change, only one set of broadcast IPIs is sent. This reduces boot time, especially for platforms with large number of cores. Single CPU initialization is still possible, it is used for hotplug. During wakeup from S3 APs are started one by one. It should be possible to enable parallel execution there as well, but I don't have a way of testing it as of now. Signed-off-by: Krystian Hebel <[email protected]>
1 parent 7394b75 commit aacc6f2

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

xen/arch/x86/include/asm/smp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ DECLARE_PER_CPU(cpumask_var_t, send_ipi_cpumask);
3131
extern bool park_offline_cpus;
3232

3333
void smp_send_nmi_allbutself(void);
34+
void smp_send_init_sipi_sipi_allbutself(void);
3435

3536
void send_IPI_mask(const cpumask_t *mask, int vector);
3637
void send_IPI_self(int vector);

xen/arch/x86/setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,6 +2079,8 @@ void asmlinkage __init noreturn __start_xen(void)
20792079
stack_base[i] = cpu_alloc_stack(i);
20802080
}
20812081

2082+
smp_send_init_sipi_sipi_allbutself();
2083+
20822084
for_each_present_cpu ( i )
20832085
{
20842086
if ( (park_offline_cpus || num_online_cpus() < max_cpus) &&

xen/arch/x86/smpboot.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ static int wake_aps_in_txt(void)
455455

456456
static int wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
457457
{
458-
unsigned long send_status = 0, accept_status = 0;
458+
unsigned long send_status = 0, accept_status = 0, sh = 0;
459459
int maxlvt, timeout, i;
460460

461461
/*
@@ -478,6 +478,12 @@ static int wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
478478
if ( ap_boot_method == AP_BOOT_TXT )
479479
return wake_aps_in_txt();
480480

481+
/*
482+
* Use destination shorthand for broadcasting IPIs during boot.
483+
*/
484+
if ( phys_apicid == BAD_APICID )
485+
sh = APIC_DEST_ALLBUT;
486+
481487
/*
482488
* Be paranoid about clearing APIC errors.
483489
*/
@@ -491,7 +497,7 @@ static int wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
491497
/*
492498
* Turn INIT on target chip via IPI
493499
*/
494-
apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT,
500+
apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT | sh,
495501
phys_apicid);
496502

497503
if ( !x2apic_enabled )
@@ -508,7 +514,7 @@ static int wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
508514

509515
Dprintk("Deasserting INIT.\n");
510516

511-
apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid);
517+
apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT | sh, phys_apicid);
512518

513519
Dprintk("Waiting for send to finish...\n");
514520
timeout = 0;
@@ -545,7 +551,7 @@ static int wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
545551
* STARTUP IPI
546552
* Boot on the stack
547553
*/
548-
apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12), phys_apicid);
554+
apic_icr_write(APIC_DM_STARTUP | (start_eip >> 12) | sh, phys_apicid);
549555

550556
if ( !x2apic_enabled )
551557
{
@@ -1193,6 +1199,23 @@ static struct notifier_block cpu_smpboot_nfb = {
11931199
.notifier_call = cpu_smpboot_callback
11941200
};
11951201

1202+
void smp_send_init_sipi_sipi_allbutself(void)
1203+
{
1204+
unsigned long start_eip;
1205+
start_eip = bootsym_phys(entry_SIPI16);
1206+
1207+
/* start_eip needs be page aligned, and below the 1M boundary. */
1208+
if ( start_eip & ~0xff000 )
1209+
panic("AP trampoline %#lx not suitably positioned\n", start_eip);
1210+
1211+
/* So we see what's up */
1212+
if ( opt_cpu_info )
1213+
printk("Booting APs in parallel, eip %lx\n", start_eip);
1214+
1215+
/* Starting actual broadcast IPI sequence... */
1216+
wakeup_secondary_cpu(BAD_APICID, start_eip);
1217+
}
1218+
11961219
void __init smp_prepare_cpus(void)
11971220
{
11981221
/*

0 commit comments

Comments
 (0)