.. | .. |
---|
95 | 95 | return 0; |
---|
96 | 96 | } |
---|
97 | 97 | |
---|
98 | | - if (boot_cpu_data.extended_cpuid_level < SVM_CPUID_FUNC) { |
---|
99 | | - if (msg) |
---|
100 | | - *msg = "can't execute cpuid_8000000a"; |
---|
101 | | - return 0; |
---|
102 | | - } |
---|
103 | | - |
---|
104 | 98 | if (!boot_cpu_has(X86_FEATURE_SVM)) { |
---|
105 | 99 | if (msg) |
---|
106 | 100 | *msg = "svm not available"; |
---|
.. | .. |
---|
120 | 114 | |
---|
121 | 115 | wrmsrl(MSR_VM_HSAVE_PA, 0); |
---|
122 | 116 | rdmsrl(MSR_EFER, efer); |
---|
123 | | - wrmsrl(MSR_EFER, efer & ~EFER_SVME); |
---|
| 117 | + if (efer & EFER_SVME) { |
---|
| 118 | + /* |
---|
| 119 | + * Force GIF=1 prior to disabling SVM to ensure INIT and NMI |
---|
| 120 | + * aren't blocked, e.g. if a fatal error occurred between CLGI |
---|
| 121 | + * and STGI. Note, STGI may #UD if SVM is disabled from NMI |
---|
| 122 | + * context between reading EFER and executing STGI. In that |
---|
| 123 | + * case, GIF must already be set, otherwise the NMI would have |
---|
| 124 | + * been blocked, so just eat the fault. |
---|
| 125 | + */ |
---|
| 126 | + asm_volatile_goto("1: stgi\n\t" |
---|
| 127 | + _ASM_EXTABLE(1b, %l[fault]) |
---|
| 128 | + ::: "memory" : fault); |
---|
| 129 | +fault: |
---|
| 130 | + wrmsrl(MSR_EFER, efer & ~EFER_SVME); |
---|
| 131 | + } |
---|
124 | 132 | } |
---|
125 | 133 | |
---|
126 | 134 | /** Makes sure SVM is disabled, if it is supported on the CPU |
---|