x86/smpboot: Allow making an INIT IPI conditional

A subsequent change is going to introduce SKINIT support, wherein the APs will
be already be in the wait-for-SIPI state, and an INIT must not be sent.

Introduce a send_INIT boolean, so we can control sending an INIT IPI
separately from sending SIPIs.

No functional change.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
This commit is contained in:
Andrew Cooper committed 2021-01-29 11:59:54 +00:00
1 parent dbfee5918c
commit f31029cc73
1 file changed
+43 -39
+43 -39
View File
@@ -424,6 +424,7 @@ static int wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
{
unsigned long send_status = 0, accept_status = 0;
int maxlvt, timeout, i;
bool send_INIT = true;
/*
* Some versions of tboot might be able to handle the entire wake sequence
@@ -438,49 +439,52 @@ static int wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
apic_write(APIC_ESR, 0);
apic_read(APIC_ESR);
Dprintk("Asserting INIT.\n");
/*
* Turn INIT on target chip via IPI
*/
apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT,
phys_apicid);
if ( !x2apic_enabled )
if ( send_INIT )
{
Dprintk("Waiting for send to finish...\n");
timeout = 0;
do {
Dprintk("+");
udelay(100);
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
} while ( send_status && (timeout++ < 1000) );
Dprintk("Asserting INIT.\n");
mdelay(10);
Dprintk("Deasserting INIT.\n");
apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid);
Dprintk("Waiting for send to finish...\n");
timeout = 0;
do {
Dprintk("+");
udelay(100);
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
} while ( send_status && (timeout++ < 1000) );
}
else if ( tboot_in_measured_env() )
{
/*
* With tboot AP is actually spinning in a mini-guest before
* receiving INIT. Upon receiving INIT ipi, AP need time to VMExit,
* update VMCS to tracking SIPIs and VMResume.
*
* While AP is in root mode handling the INIT the CPU will drop
* any SIPIs
* Turn INIT on target chip via IPI
*/
udelay(10);
apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT,
phys_apicid);
if ( !x2apic_enabled )
{
Dprintk("Waiting for send to finish...\n");
timeout = 0;
do {
Dprintk("+");
udelay(100);
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
} while ( send_status && (timeout++ < 1000) );
mdelay(10);
Dprintk("Deasserting INIT.\n");
apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid);
Dprintk("Waiting for send to finish...\n");
timeout = 0;
do {
Dprintk("+");
udelay(100);
send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
} while ( send_status && (timeout++ < 1000) );
}
else if ( tboot_in_measured_env() )
{
/*
* With tboot AP is actually spinning in a mini-guest before
* receiving INIT. Upon receiving INIT ipi, AP need time to VMExit,
* update VMCS to tracking SIPIs and VMResume.
*
* While AP is in root mode handling the INIT the CPU will drop
* any SIPIs
*/
udelay(10);
}
}
maxlvt = get_maxlvt();
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.