x86/lapic: Set EXTINT on BSP only

When Linux is booted, the kernel reports

    "do_IRQ: 1.55 No irq handler for vector"

So far it comes with payloads SeaBIOS and depthcharge, not with
Grub. We assume Grub does something to avoid this problem.

AMD bug tracker system (JIRA PLAT-21393) says the APs can not be set
EXTINT delivery mode.

In Intel 64 and IA-32 Architectures Software Developer’s Manual volume
3A, see chapter 10.5.1 Local Vector Table, it says:
"The APIC architecture supports only one ExtINT source in a system,
usually contained in the compatibility bridge. Only one processor in the
system should have an LVT entry configured to use the ExtINT delivery
mode."

Tested on mandolin (Picasso) board, the error in dmesg is gone.

The bug 153677727 has two parts.
1. Soft lockup
2. do_IRQ 1.55.
The soft lockup issued has been fixed by
https://review.coreboot.org/c/coreboot/+/41128

BUG=b:153677727
TEST=mandolin

Change-Id: I2956dcaad87cc1466deeca703748de33390b7603
Signed-off-by: Zheng Bao <zheng.bao@amd.com>
Signed-off-by: Zheng Bao <fishbaozi@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/42219
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Zheng Bao 2020-06-10 11:04:36 +08:00 committed by Felix Held
parent 49e0e00168
commit aac79e0b8f
1 changed files with 11 additions and 15 deletions

View File

@ -2,16 +2,11 @@
#include <cpu/x86/lapic.h> #include <cpu/x86/lapic.h>
#include <console/console.h> #include <console/console.h>
#include <smp/node.h>
void do_lapic_init(void) void do_lapic_init(void)
{ {
/* this is so interrupts work. This is very limited scope -- uint32_t lvt0_val;
* linux will do better later, we hope ...
*/
/* this is the first way we learned to do it. It fails on real SMP
* stuff. So we have to do things differently ...
* see the Intel mp1.4 spec, page A-3
*/
printk(BIOS_INFO, "Setting up local APIC...\n"); printk(BIOS_INFO, "Setting up local APIC...\n");
@ -28,15 +23,16 @@ void do_lapic_init(void)
lapic_write_around(LAPIC_SPIV, lapic_write_around(LAPIC_SPIV,
(lapic_read_around(LAPIC_SPIV) & ~(LAPIC_VECTOR_MASK)) (lapic_read_around(LAPIC_SPIV) & ~(LAPIC_VECTOR_MASK))
| LAPIC_SPIV_ENABLE); | LAPIC_SPIV_ENABLE);
lapic_write_around(LAPIC_LVT0,
(lapic_read_around(LAPIC_LVT0) & lvt0_val = (lapic_read_around(LAPIC_LVT0) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |
LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY | LAPIC_LVT_REMOTE_IRR | LAPIC_INPUT_POLARITY |
LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1 | LAPIC_SEND_PENDING | LAPIC_LVT_RESERVED_1)) |
LAPIC_DELIVERY_MODE_MASK)) (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING);
| (LAPIC_LVT_REMOTE_IRR | LAPIC_SEND_PENDING | if (boot_cpu())
LAPIC_DELIVERY_MODE_EXTINT) lvt0_val = SET_LAPIC_DELIVERY_MODE(lvt0_val, LAPIC_MODE_EXINT);
); lapic_write_around(LAPIC_LVT0, lvt0_val);
lapic_write_around(LAPIC_LVT1, lapic_write_around(LAPIC_LVT1,
(lapic_read_around(LAPIC_LVT1) & (lapic_read_around(LAPIC_LVT1) &
~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | ~(LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER |