Loading...
1/* CPU virtualization extensions handling
2 *
3 * This should carry the code for handling CPU virtualization extensions
4 * that needs to live in the kernel core.
5 *
6 * Author: Eduardo Habkost <ehabkost@redhat.com>
7 *
8 * Copyright (C) 2008, Red Hat Inc.
9 *
10 * Contains code from KVM, Copyright (C) 2006 Qumranet, Inc.
11 *
12 * This work is licensed under the terms of the GNU GPL, version 2. See
13 * the COPYING file in the top-level directory.
14 */
15#ifndef _ASM_X86_VIRTEX_H
16#define _ASM_X86_VIRTEX_H
17
18#include <asm/processor.h>
19
20#include <asm/vmx.h>
21#include <asm/svm.h>
22#include <asm/tlbflush.h>
23
24/*
25 * VMX functions:
26 */
27
28static inline int cpu_has_vmx(void)
29{
30 unsigned long ecx = cpuid_ecx(1);
31 return test_bit(5, &ecx); /* CPUID.1:ECX.VMX[bit 5] -> VT */
32}
33
34
35/** Disable VMX on the current CPU
36 *
37 * vmxoff causes a undefined-opcode exception if vmxon was not run
38 * on the CPU previously. Only call this function if you know VMX
39 * is enabled.
40 */
41static inline void cpu_vmxoff(void)
42{
43 asm volatile (ASM_VMX_VMXOFF : : : "cc");
44 cr4_clear_bits(X86_CR4_VMXE);
45}
46
47static inline int cpu_vmx_enabled(void)
48{
49 return __read_cr4() & X86_CR4_VMXE;
50}
51
52/** Disable VMX if it is enabled on the current CPU
53 *
54 * You shouldn't call this if cpu_has_vmx() returns 0.
55 */
56static inline void __cpu_emergency_vmxoff(void)
57{
58 if (cpu_vmx_enabled())
59 cpu_vmxoff();
60}
61
62/** Disable VMX if it is supported and enabled on the current CPU
63 */
64static inline void cpu_emergency_vmxoff(void)
65{
66 if (cpu_has_vmx())
67 __cpu_emergency_vmxoff();
68}
69
70
71
72
73/*
74 * SVM functions:
75 */
76
77/** Check if the CPU has SVM support
78 *
79 * You can use the 'msg' arg to get a message describing the problem,
80 * if the function returns zero. Simply pass NULL if you are not interested
81 * on the messages; gcc should take care of not generating code for
82 * the messages on this case.
83 */
84static inline int cpu_has_svm(const char **msg)
85{
86 uint32_t eax, ebx, ecx, edx;
87
88 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) {
89 if (msg)
90 *msg = "not amd";
91 return 0;
92 }
93
94 cpuid(0x80000000, &eax, &ebx, &ecx, &edx);
95 if (eax < SVM_CPUID_FUNC) {
96 if (msg)
97 *msg = "can't execute cpuid_8000000a";
98 return 0;
99 }
100
101 cpuid(0x80000001, &eax, &ebx, &ecx, &edx);
102 if (!(ecx & (1 << SVM_CPUID_FEATURE_SHIFT))) {
103 if (msg)
104 *msg = "svm not available";
105 return 0;
106 }
107 return 1;
108}
109
110
111/** Disable SVM on the current CPU
112 *
113 * You should call this only if cpu_has_svm() returned true.
114 */
115static inline void cpu_svm_disable(void)
116{
117 uint64_t efer;
118
119 wrmsrl(MSR_VM_HSAVE_PA, 0);
120 rdmsrl(MSR_EFER, efer);
121 wrmsrl(MSR_EFER, efer & ~EFER_SVME);
122}
123
124/** Makes sure SVM is disabled, if it is supported on the CPU
125 */
126static inline void cpu_emergency_svm_disable(void)
127{
128 if (cpu_has_svm(NULL))
129 cpu_svm_disable();
130}
131
132#endif /* _ASM_X86_VIRTEX_H */
1/* SPDX-License-Identifier: GPL-2.0-only */
2/* CPU virtualization extensions handling
3 *
4 * This should carry the code for handling CPU virtualization extensions
5 * that needs to live in the kernel core.
6 *
7 * Author: Eduardo Habkost <ehabkost@redhat.com>
8 *
9 * Copyright (C) 2008, Red Hat Inc.
10 *
11 * Contains code from KVM, Copyright (C) 2006 Qumranet, Inc.
12 */
13#ifndef _ASM_X86_VIRTEX_H
14#define _ASM_X86_VIRTEX_H
15
16#include <asm/processor.h>
17
18#include <asm/vmx.h>
19#include <asm/svm.h>
20#include <asm/tlbflush.h>
21
22/*
23 * VMX functions:
24 */
25
26static inline int cpu_has_vmx(void)
27{
28 unsigned long ecx = cpuid_ecx(1);
29 return test_bit(5, &ecx); /* CPUID.1:ECX.VMX[bit 5] -> VT */
30}
31
32
33/**
34 * cpu_vmxoff() - Disable VMX on the current CPU
35 *
36 * Disable VMX and clear CR4.VMXE (even if VMXOFF faults)
37 *
38 * Note, VMXOFF causes a #UD if the CPU is !post-VMXON, but it's impossible to
39 * atomically track post-VMXON state, e.g. this may be called in NMI context.
40 * Eat all faults as all other faults on VMXOFF faults are mode related, i.e.
41 * faults are guaranteed to be due to the !post-VMXON check unless the CPU is
42 * magically in RM, VM86, compat mode, or at CPL>0.
43 */
44static inline int cpu_vmxoff(void)
45{
46 asm_volatile_goto("1: vmxoff\n\t"
47 _ASM_EXTABLE(1b, %l[fault])
48 ::: "cc", "memory" : fault);
49
50 cr4_clear_bits(X86_CR4_VMXE);
51 return 0;
52
53fault:
54 cr4_clear_bits(X86_CR4_VMXE);
55 return -EIO;
56}
57
58static inline int cpu_vmx_enabled(void)
59{
60 return __read_cr4() & X86_CR4_VMXE;
61}
62
63/** Disable VMX if it is enabled on the current CPU
64 *
65 * You shouldn't call this if cpu_has_vmx() returns 0.
66 */
67static inline void __cpu_emergency_vmxoff(void)
68{
69 if (cpu_vmx_enabled())
70 cpu_vmxoff();
71}
72
73/** Disable VMX if it is supported and enabled on the current CPU
74 */
75static inline void cpu_emergency_vmxoff(void)
76{
77 if (cpu_has_vmx())
78 __cpu_emergency_vmxoff();
79}
80
81
82
83
84/*
85 * SVM functions:
86 */
87
88/** Check if the CPU has SVM support
89 *
90 * You can use the 'msg' arg to get a message describing the problem,
91 * if the function returns zero. Simply pass NULL if you are not interested
92 * on the messages; gcc should take care of not generating code for
93 * the messages on this case.
94 */
95static inline int cpu_has_svm(const char **msg)
96{
97 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
98 boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) {
99 if (msg)
100 *msg = "not amd or hygon";
101 return 0;
102 }
103
104 if (boot_cpu_data.extended_cpuid_level < SVM_CPUID_FUNC) {
105 if (msg)
106 *msg = "can't execute cpuid_8000000a";
107 return 0;
108 }
109
110 if (!boot_cpu_has(X86_FEATURE_SVM)) {
111 if (msg)
112 *msg = "svm not available";
113 return 0;
114 }
115 return 1;
116}
117
118
119/** Disable SVM on the current CPU
120 *
121 * You should call this only if cpu_has_svm() returned true.
122 */
123static inline void cpu_svm_disable(void)
124{
125 uint64_t efer;
126
127 wrmsrl(MSR_VM_HSAVE_PA, 0);
128 rdmsrl(MSR_EFER, efer);
129 wrmsrl(MSR_EFER, efer & ~EFER_SVME);
130}
131
132/** Makes sure SVM is disabled, if it is supported on the CPU
133 */
134static inline void cpu_emergency_svm_disable(void)
135{
136 if (cpu_has_svm(NULL))
137 cpu_svm_disable();
138}
139
140#endif /* _ASM_X86_VIRTEX_H */