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