| .. | .. |
|---|
| 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 |
|---|