1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2021, Google LLC. 4 */ 5 6#include "apic.h" 7 8void 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 15void 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 37void 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