blob: 8e0449a5fe87bd53774d71a5c165d68fd7801689 [file] [log] [blame]
Angel Ponsf23ae0b2020-04-02 23:48:12 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Martin Roth6add44b2017-02-09 17:51:20 -08002
Kyösti Mälkkic8d26c02021-06-06 17:07:25 +03003#include <assert.h>
Elyes Haouas45d32052022-10-07 10:07:12 +02004#include <console/console.h>
Kyösti Mälkkidea42e02021-05-31 20:26:16 +03005#include <cpu/cpu.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00006#include <cpu/x86/lapic.h>
Kyösti Mälkki242f1d92021-06-06 16:58:19 +03007#include <cpu/x86/lapic_def.h>
8#include <cpu/x86/msr.h>
Kyösti Mälkkic78c46d2021-06-20 15:44:32 +03009#include <smp/node.h>
Elyes Haouas45d32052022-10-07 10:07:12 +020010#include <types.h>
Kyösti Mälkki176c8872021-05-29 20:33:22 +030011
Kyösti Mälkki0834b222023-07-08 20:17:59 +030012static bool quirk_x2apic_allowed;
13
Subrata Banik2125a172022-07-12 10:55:21 +000014void enable_lapic_mode(bool try_set_x2apic)
Kyösti Mälkki242f1d92021-06-06 16:58:19 +030015{
Kyösti Mälkkic8d26c02021-06-06 17:07:25 +030016 uintptr_t apic_base;
Subrata Banik2125a172022-07-12 10:55:21 +000017 bool use_x2apic = false;
Kyösti Mälkki242f1d92021-06-06 16:58:19 +030018 msr_t msr;
Kyösti Mälkkiff556ca2021-06-06 22:56:41 +030019
Kyösti Mälkki242f1d92021-06-06 16:58:19 +030020 msr = rdmsr(LAPIC_BASE_MSR);
Kyösti Mälkkic8d26c02021-06-06 17:07:25 +030021 if (!(msr.lo & LAPIC_BASE_MSR_ENABLE)) {
22 msr.hi &= 0xffffff00;
23 msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK;
24 msr.lo |= LAPIC_DEFAULT_BASE;
25 msr.lo |= LAPIC_BASE_MSR_ENABLE;
26 wrmsr(LAPIC_BASE_MSR, msr);
27 msr = rdmsr(LAPIC_BASE_MSR);
28 }
Kyösti Mälkkiff556ca2021-06-06 22:56:41 +030029
Kyösti Mälkkic8d26c02021-06-06 17:07:25 +030030 ASSERT(msr.lo & LAPIC_BASE_MSR_ENABLE);
31
32 apic_base = msr.lo & LAPIC_BASE_MSR_ADDR_MASK;
33 ASSERT(apic_base == LAPIC_DEFAULT_BASE);
34
Subrata Banik2125a172022-07-12 10:55:21 +000035 if (try_set_x2apic)
Kyösti Mälkkic8d26c02021-06-06 17:07:25 +030036 use_x2apic = !!(cpu_get_feature_flags_ecx() & CPUID_X2APIC);
Kyösti Mälkkic8d26c02021-06-06 17:07:25 +030037
38 if (use_x2apic == !!(msr.lo & LAPIC_BASE_MSR_X2APIC_MODE)) {
39 printk(BIOS_INFO, "LAPIC 0x%x in %s mode.\n", lapicid(),
40 use_x2apic ? "X2APIC" : "XAPIC");
41 } else if (use_x2apic) {
42 msr.lo |= LAPIC_BASE_MSR_X2APIC_MODE;
43 wrmsr(LAPIC_BASE_MSR, msr);
44 msr = rdmsr(LAPIC_BASE_MSR);
45 ASSERT(!!(msr.lo & LAPIC_BASE_MSR_X2APIC_MODE));
46 printk(BIOS_INFO, "LAPIC 0x%x switched to X2APIC mode.\n", lapicid());
47 } else {
48 die("Switching from X2APIC to XAPIC mode is not implemented.");
49 }
50
Kyösti Mälkki0834b222023-07-08 20:17:59 +030051 if (CONFIG(X2APIC_LATE_WORKAROUND) && use_x2apic)
52 quirk_x2apic_allowed = true;
Kyösti Mälkki242f1d92021-06-06 16:58:19 +030053}
54
Subrata Banik2125a172022-07-12 10:55:21 +000055void enable_lapic(void)
56{
57 bool try_set_x2apic = true;
58
Kyösti Mälkki0834b222023-07-08 20:17:59 +030059 if (CONFIG(XAPIC_ONLY))
Subrata Banik2125a172022-07-12 10:55:21 +000060 try_set_x2apic = false;
Kyösti Mälkki0834b222023-07-08 20:17:59 +030061 else if (CONFIG(X2APIC_LATE_WORKAROUND))
62 try_set_x2apic = quirk_x2apic_allowed;
Subrata Banik2125a172022-07-12 10:55:21 +000063
64 enable_lapic_mode(try_set_x2apic);
65}
66
Kyösti Mälkki242f1d92021-06-06 16:58:19 +030067void disable_lapic(void)
68{
69 msr_t msr;
70 msr = rdmsr(LAPIC_BASE_MSR);
Kyösti Mälkkic8d26c02021-06-06 17:07:25 +030071 msr.lo &= ~(LAPIC_BASE_MSR_ENABLE | LAPIC_BASE_MSR_X2APIC_MODE);
Kyösti Mälkki242f1d92021-06-06 16:58:19 +030072 wrmsr(LAPIC_BASE_MSR, msr);
73}
74
Kyösti Mälkkidea42e02021-05-31 20:26:16 +030075uintptr_t cpu_get_lapic_addr(void)
76{
77 return LAPIC_DEFAULT_BASE;
78}
79
Kyösti Mälkki9ec72272021-10-17 08:34:31 +030080void setup_lapic_interrupts(void)
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000081{
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000082 /*
83 * Set Task Priority to 'accept all'.
84 */
Kyösti Mälkki0cfa9112021-05-31 10:38:45 +030085 lapic_update32(LAPIC_TASKPRI, ~LAPIC_TPRI_MASK, 0);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000086
Kyösti Mälkki90f54c92021-06-20 19:43:37 +030087 /* Set spurious interrupt vector to 0 and keep LAPIC enabled to
88 be able to clear LVT register mask bits. */
Kyösti Mälkki0cfa9112021-05-31 10:38:45 +030089 lapic_update32(LAPIC_SPIV, ~LAPIC_VECTOR_MASK, LAPIC_SPIV_ENABLE);
90
Kyösti Mälkki90f54c92021-06-20 19:43:37 +030091 /* Put the local APIC in virtual wire mode */
Kyösti Mälkki7da871e2021-06-20 14:58:36 +030092 uint32_t mask = LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | LAPIC_INPUT_POLARITY |
Kyösti Mälkki0cfa9112021-05-31 10:38:45 +030093 LAPIC_DELIVERY_MODE_MASK;
94
Kyösti Mälkkic78c46d2021-06-20 15:44:32 +030095 if (boot_cpu())
96 lapic_update32(LAPIC_LVT0, ~mask, LAPIC_DELIVERY_MODE_EXTINT);
97 else
98 lapic_update32(LAPIC_LVT0, ~mask, LAPIC_LVT_MASKED |
99 LAPIC_DELIVERY_MODE_EXTINT);
Kyösti Mälkki0cfa9112021-05-31 10:38:45 +0300100
Kyösti Mälkki7da871e2021-06-20 14:58:36 +0300101 lapic_update32(LAPIC_LVT1, ~mask, LAPIC_DELIVERY_MODE_NMI);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000102}