1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2021, Google LLC. 4 */ 5 6 #include "apic.h" 7 8 void apic_disable(void) 9 { 10 wrmsr(MSR_IA32_APICBASE, 11 rdmsr(MSR_IA32_APICBASE) & 12 ~(MSR_IA32_APICBASE_ENABLE | MSR_IA32_APICBASE_EXTD)); 13 } 14 15 void xapic_enable(void) 16 { 17 uint64_t val = rdmsr(MSR_IA32_APICBASE); 18 19 /* Per SDM: to enable xAPIC when in x2APIC must first disable APIC */ 20 if (val & MSR_IA32_APICBASE_EXTD) { 21 apic_disable(); 22 wrmsr(MSR_IA32_APICBASE, 23 rdmsr(MSR_IA32_APICBASE) | MSR_IA32_APICBASE_ENABLE); 24 } else if (!(val & MSR_IA32_APICBASE_ENABLE)) { 25 wrmsr(MSR_IA32_APICBASE, val | MSR_IA32_APICBASE_ENABLE); 26 } 27 28 /* 29 * Per SDM: reset value of spurious interrupt vector register has the 30 * APIC software enabled bit=0. It must be enabled in addition to the 31 * enable bit in the MSR. 32 */ 33 val = xapic_read_reg(APIC_SPIV) | APIC_SPIV_APIC_ENABLED; 34 xapic_write_reg(APIC_SPIV, val); 35 } 36 37 void x2apic_enable(void) 38 { 39 wrmsr(MSR_IA32_APICBASE, rdmsr(MSR_IA32_APICBASE) | 40 MSR_IA32_APICBASE_ENABLE | MSR_IA32_APICBASE_EXTD); 41 x2apic_write_reg(APIC_SPIV, 42 x2apic_read_reg(APIC_SPIV) | APIC_SPIV_APIC_ENABLED); 43 } 44