Angel Pons | f23ae0b | 2020-04-02 23:48:12 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Martin Roth | 6add44b | 2017-02-09 17:51:20 -0800 | [diff] [blame] | 2 | |
Kyösti Mälkki | c8d26c0 | 2021-06-06 17:07:25 +0300 | [diff] [blame] | 3 | #include <assert.h> |
Elyes Haouas | 45d3205 | 2022-10-07 10:07:12 +0200 | [diff] [blame] | 4 | #include <console/console.h> |
Kyösti Mälkki | dea42e0 | 2021-05-31 20:26:16 +0300 | [diff] [blame] | 5 | #include <cpu/cpu.h> |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 6 | #include <cpu/x86/lapic.h> |
Kyösti Mälkki | 242f1d9 | 2021-06-06 16:58:19 +0300 | [diff] [blame] | 7 | #include <cpu/x86/lapic_def.h> |
| 8 | #include <cpu/x86/msr.h> |
Kyösti Mälkki | c78c46d | 2021-06-20 15:44:32 +0300 | [diff] [blame] | 9 | #include <smp/node.h> |
Elyes Haouas | 45d3205 | 2022-10-07 10:07:12 +0200 | [diff] [blame] | 10 | #include <types.h> |
Kyösti Mälkki | 176c887 | 2021-05-29 20:33:22 +0300 | [diff] [blame] | 11 | |
Kyösti Mälkki | 0834b22 | 2023-07-08 20:17:59 +0300 | [diff] [blame^] | 12 | static bool quirk_x2apic_allowed; |
| 13 | |
Subrata Banik | 2125a17 | 2022-07-12 10:55:21 +0000 | [diff] [blame] | 14 | void enable_lapic_mode(bool try_set_x2apic) |
Kyösti Mälkki | 242f1d9 | 2021-06-06 16:58:19 +0300 | [diff] [blame] | 15 | { |
Kyösti Mälkki | c8d26c0 | 2021-06-06 17:07:25 +0300 | [diff] [blame] | 16 | uintptr_t apic_base; |
Subrata Banik | 2125a17 | 2022-07-12 10:55:21 +0000 | [diff] [blame] | 17 | bool use_x2apic = false; |
Kyösti Mälkki | 242f1d9 | 2021-06-06 16:58:19 +0300 | [diff] [blame] | 18 | msr_t msr; |
Kyösti Mälkki | ff556ca | 2021-06-06 22:56:41 +0300 | [diff] [blame] | 19 | |
Kyösti Mälkki | 242f1d9 | 2021-06-06 16:58:19 +0300 | [diff] [blame] | 20 | msr = rdmsr(LAPIC_BASE_MSR); |
Kyösti Mälkki | c8d26c0 | 2021-06-06 17:07:25 +0300 | [diff] [blame] | 21 | 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älkki | ff556ca | 2021-06-06 22:56:41 +0300 | [diff] [blame] | 29 | |
Kyösti Mälkki | c8d26c0 | 2021-06-06 17:07:25 +0300 | [diff] [blame] | 30 | 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 Banik | 2125a17 | 2022-07-12 10:55:21 +0000 | [diff] [blame] | 35 | if (try_set_x2apic) |
Kyösti Mälkki | c8d26c0 | 2021-06-06 17:07:25 +0300 | [diff] [blame] | 36 | use_x2apic = !!(cpu_get_feature_flags_ecx() & CPUID_X2APIC); |
Kyösti Mälkki | c8d26c0 | 2021-06-06 17:07:25 +0300 | [diff] [blame] | 37 | |
| 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älkki | 0834b22 | 2023-07-08 20:17:59 +0300 | [diff] [blame^] | 51 | if (CONFIG(X2APIC_LATE_WORKAROUND) && use_x2apic) |
| 52 | quirk_x2apic_allowed = true; |
Kyösti Mälkki | 242f1d9 | 2021-06-06 16:58:19 +0300 | [diff] [blame] | 53 | } |
| 54 | |
Subrata Banik | 2125a17 | 2022-07-12 10:55:21 +0000 | [diff] [blame] | 55 | void enable_lapic(void) |
| 56 | { |
| 57 | bool try_set_x2apic = true; |
| 58 | |
Kyösti Mälkki | 0834b22 | 2023-07-08 20:17:59 +0300 | [diff] [blame^] | 59 | if (CONFIG(XAPIC_ONLY)) |
Subrata Banik | 2125a17 | 2022-07-12 10:55:21 +0000 | [diff] [blame] | 60 | try_set_x2apic = false; |
Kyösti Mälkki | 0834b22 | 2023-07-08 20:17:59 +0300 | [diff] [blame^] | 61 | else if (CONFIG(X2APIC_LATE_WORKAROUND)) |
| 62 | try_set_x2apic = quirk_x2apic_allowed; |
Subrata Banik | 2125a17 | 2022-07-12 10:55:21 +0000 | [diff] [blame] | 63 | |
| 64 | enable_lapic_mode(try_set_x2apic); |
| 65 | } |
| 66 | |
Kyösti Mälkki | 242f1d9 | 2021-06-06 16:58:19 +0300 | [diff] [blame] | 67 | void disable_lapic(void) |
| 68 | { |
| 69 | msr_t msr; |
| 70 | msr = rdmsr(LAPIC_BASE_MSR); |
Kyösti Mälkki | c8d26c0 | 2021-06-06 17:07:25 +0300 | [diff] [blame] | 71 | msr.lo &= ~(LAPIC_BASE_MSR_ENABLE | LAPIC_BASE_MSR_X2APIC_MODE); |
Kyösti Mälkki | 242f1d9 | 2021-06-06 16:58:19 +0300 | [diff] [blame] | 72 | wrmsr(LAPIC_BASE_MSR, msr); |
| 73 | } |
| 74 | |
Kyösti Mälkki | dea42e0 | 2021-05-31 20:26:16 +0300 | [diff] [blame] | 75 | uintptr_t cpu_get_lapic_addr(void) |
| 76 | { |
| 77 | return LAPIC_DEFAULT_BASE; |
| 78 | } |
| 79 | |
Kyösti Mälkki | 9ec7227 | 2021-10-17 08:34:31 +0300 | [diff] [blame] | 80 | void setup_lapic_interrupts(void) |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 81 | { |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 82 | /* |
| 83 | * Set Task Priority to 'accept all'. |
| 84 | */ |
Kyösti Mälkki | 0cfa911 | 2021-05-31 10:38:45 +0300 | [diff] [blame] | 85 | lapic_update32(LAPIC_TASKPRI, ~LAPIC_TPRI_MASK, 0); |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 86 | |
Kyösti Mälkki | 90f54c9 | 2021-06-20 19:43:37 +0300 | [diff] [blame] | 87 | /* Set spurious interrupt vector to 0 and keep LAPIC enabled to |
| 88 | be able to clear LVT register mask bits. */ |
Kyösti Mälkki | 0cfa911 | 2021-05-31 10:38:45 +0300 | [diff] [blame] | 89 | lapic_update32(LAPIC_SPIV, ~LAPIC_VECTOR_MASK, LAPIC_SPIV_ENABLE); |
| 90 | |
Kyösti Mälkki | 90f54c9 | 2021-06-20 19:43:37 +0300 | [diff] [blame] | 91 | /* Put the local APIC in virtual wire mode */ |
Kyösti Mälkki | 7da871e | 2021-06-20 14:58:36 +0300 | [diff] [blame] | 92 | uint32_t mask = LAPIC_LVT_MASKED | LAPIC_LVT_LEVEL_TRIGGER | LAPIC_INPUT_POLARITY | |
Kyösti Mälkki | 0cfa911 | 2021-05-31 10:38:45 +0300 | [diff] [blame] | 93 | LAPIC_DELIVERY_MODE_MASK; |
| 94 | |
Kyösti Mälkki | c78c46d | 2021-06-20 15:44:32 +0300 | [diff] [blame] | 95 | 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älkki | 0cfa911 | 2021-05-31 10:38:45 +0300 | [diff] [blame] | 100 | |
Kyösti Mälkki | 7da871e | 2021-06-20 14:58:36 +0300 | [diff] [blame] | 101 | lapic_update32(LAPIC_LVT1, ~mask, LAPIC_DELIVERY_MODE_NMI); |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 102 | } |