cpu/x86/lapic: Add wait_ipi_completion() helpers

Change-Id: Ib9c404cb55b96dcc5639287c214c5c8f468c0529
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/55192
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Kyösti Mälkki 2021-05-30 10:17:52 +03:00
parent a4ceba4ae5
commit 68fe11beb0
1 changed files with 42 additions and 51 deletions

View File

@ -88,9 +88,25 @@ static void recover_lowest_1M(void)
memcpy(lowmem_backup_ptr, lowmem_backup, lowmem_backup_size);
}
static uint32_t wait_for_ipi_completion(const int timeout_ms)
{
int loops = timeout_ms * 10;
uint32_t send_status;
/* wait for the ipi send to finish */
printk(BIOS_SPEW, "Waiting for send to finish...\n");
do {
printk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_busy();
} while (send_status && (--loops > 0));
return send_status;
}
static int lapic_start_cpu(unsigned long apicid)
{
int timeout;
const int timeout_100ms = 100;
uint32_t send_status, accept_status;
int j, maxlvt;
@ -105,14 +121,8 @@ static int lapic_start_cpu(unsigned long apicid)
*/
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT, apicid);
printk(BIOS_SPEW, "Waiting for send to finish...\n");
timeout = 0;
do {
printk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_busy();
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000) {
send_status = wait_for_ipi_completion(timeout_100ms);
if (send_status) {
printk(BIOS_ERR, "CPU %ld: First APIC write timed out. "
"Disabling\n", apicid);
// too bad.
@ -131,14 +141,8 @@ static int lapic_start_cpu(unsigned long apicid)
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT, apicid);
printk(BIOS_SPEW, "Waiting for send to finish...\n");
timeout = 0;
do {
printk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_busy();
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000) {
send_status = wait_for_ipi_completion(timeout_100ms);
if (send_status) {
printk(BIOS_ERR, "CPU %ld: Second APIC write timed out. "
"Disabling\n", apicid);
// too bad.
@ -172,13 +176,7 @@ static int lapic_start_cpu(unsigned long apicid)
printk(BIOS_SPEW, "Startup point 1.\n");
printk(BIOS_SPEW, "Waiting for send to finish...\n");
timeout = 0;
do {
printk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_busy();
} while (send_status && (timeout++ < 1000));
send_status = wait_for_ipi_completion(timeout_100ms);
/*
* Give the other CPU some time to accept the IPI.
@ -306,6 +304,23 @@ static int start_cpu(struct device *cpu)
#define dprintk(LEVEL, args...) do { } while (0)
#endif
static void wait_for_ipi_completion_without_printk(const int timeout_ms)
{
int loops = timeout_ms * 10;
uint32_t send_status;
/* wait for the ipi send to finish */
dprintk(BIOS_SPEW, "Waiting for send to finish...\n");
do {
dprintk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_busy();
} while (send_status && (--loops > 0));
if (send_status)
dprintk(BIOS_ERR, "timed out\n");
}
/**
* Normally this function is defined in lapic.h as an always inline function
* that just keeps the CPU in a hlt() loop. This does not work on all CPUs.
@ -314,27 +329,14 @@ static int start_cpu(struct device *cpu)
*/
void stop_this_cpu(void)
{
int timeout;
unsigned long send_status;
const int timeout_100ms = 100;
unsigned long id = lapicid();
printk(BIOS_DEBUG, "CPU %ld going down...\n", id);
/* send an LAPIC INIT to myself */
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_INT_ASSERT | LAPIC_DM_INIT, id);
/* wait for the ipi send to finish */
dprintk(BIOS_SPEW, "Waiting for send to finish...\n");
timeout = 0;
do {
dprintk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_busy();
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000)
dprintk(BIOS_ERR, "timed out\n");
wait_for_ipi_completion_without_printk(timeout_100ms);
mdelay(10);
@ -342,18 +344,7 @@ void stop_this_cpu(void)
/* Deassert the LAPIC INIT */
lapic_send_ipi(LAPIC_INT_LEVELTRIG | LAPIC_DM_INIT, id);
dprintk(BIOS_SPEW, "Waiting for send to finish...\n");
timeout = 0;
do {
dprintk(BIOS_SPEW, "+");
udelay(100);
send_status = lapic_busy();
} while (send_status && (timeout++ < 1000));
if (timeout >= 1000)
dprintk(BIOS_ERR, "timed out\n");
wait_for_ipi_completion_without_printk(timeout_100ms);
halt();
}