diff options
| author | Alexander Potapenko <glider@google.com> | 2025-11-20 17:46:18 +0100 |
|---|---|---|
| committer | Alexander Potapenko <glider@google.com> | 2025-11-21 08:57:45 +0000 |
| commit | 880e0a0225f6667373f85f9dfa78b5d9fb6e29e2 (patch) | |
| tree | 349bf812194898ee4fb008dcc778bb63d6e0b71f /executor | |
| parent | f7a9f9c4982d10223771d3aa2287538bc08b9024 (diff) | |
executor: x86: factor out common code in rdmsr()/wrmsr()
While at it, fix a bug in rdmsr() that apparently lost the top 32 bits.
Also fix a bug in Intel's Secondary Processor-based Controls:
we were incorrectly using the top 32 bits of
X86_MSR_IA32_VMX_PROCBASED_CTLS2 to enable all the available controls
without additional setup. This only worked because rdmsr() zeroed out
those top bits.
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/common_kvm_amd64_syzos.h | 58 |
1 files changed, 21 insertions, 37 deletions
diff --git a/executor/common_kvm_amd64_syzos.h b/executor/common_kvm_amd64_syzos.h index 9971c1c7b..20b392eb4 100644 --- a/executor/common_kvm_amd64_syzos.h +++ b/executor/common_kvm_amd64_syzos.h @@ -249,11 +249,8 @@ GUEST_CODE static noinline void guest_handle_cpuid(uint32 eax, uint32 ecx) : "rbx", "rdx"); } -// Write val into an MSR register reg. -GUEST_CODE static noinline void guest_handle_wrmsr(uint64 reg, uint64 val) +GUEST_CODE static noinline void wrmsr(uint64 reg, uint64 val) { - // The wrmsr instruction takes its arguments in specific registers: - // edx:eax contains the 64-bit value to write, ecx contains the MSR address. asm volatile( "wrmsr" : @@ -263,20 +260,26 @@ GUEST_CODE static noinline void guest_handle_wrmsr(uint64 reg, uint64 val) : "memory"); } -// Read an MSR register, ignore the result. -GUEST_CODE static noinline void guest_handle_rdmsr(uint64 reg) +// Write val into an MSR register reg. +GUEST_CODE static noinline void guest_handle_wrmsr(uint64 reg, uint64 val) { - uint32 low = 0, high = 0; - // The rdmsr instruction takes the MSR address in ecx. + wrmsr(reg, val); +} + +GUEST_CODE static noinline uint64 rdmsr(uint64 msr_id) +{ + uint32 low = 0, high = 0; // nolint + // The RDMSR instruction takes the MSR address in ecx. // It puts the lower 32 bits of the MSR value into eax, and the upper. // 32 bits of the MSR value into edx. - asm volatile( - "rdmsr" - : "=a"(low), - "=d"(high) - : "c"(reg) - : // No explicit clobbers. - ); + asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr_id)); + return ((uint64)high << 32) | low; +} + +// Read an MSR register, ignore the result. +GUEST_CODE static noinline void guest_handle_rdmsr(uint64 reg) +{ + (void)rdmsr(reg); } // Write to CRn control register. @@ -488,24 +491,6 @@ GUEST_CODE static inline void write_cr4(uint64 val) asm volatile("mov %0, %%cr4" : : "r"(val)); } -GUEST_CODE static noinline void wrmsr(uint64 reg, uint64 val) -{ - asm volatile( - "wrmsr" - : - : "c"(reg), - "a"((uint32)val), - "d"((uint32)(val >> 32)) - : "memory"); -} - -GUEST_CODE static noinline uint64 rdmsr(uint32 msr_id) -{ - uint64 msr_value; - asm volatile("rdmsr" : "=A"(msr_value) : "c"(msr_id)); - return msr_value; -} - GUEST_CODE static noinline void vmwrite(uint64 field, uint64 value) { uint8 error = 0; // nolint @@ -678,10 +663,9 @@ GUEST_CODE static noinline void init_vmcs_control_fields(uint64 cpu_id, uint64 v vmwrite(VMCS_PIN_BASED_VM_EXEC_CONTROL, (uint32)vmx_msr); // Setup Secondary Processor-Based controls: enable EPT. - vmx_msr = rdmsr(X86_MSR_IA32_VMX_PROCBASED_CTLS2); - uint32 sec_exec_ctl = (uint32)(vmx_msr >> 32); // Must-be-1 bits. - sec_exec_ctl |= ((uint32)vmx_msr & SECONDARY_EXEC_ENABLE_EPT); // Allowed bits. - vmwrite(VMCS_SECONDARY_VM_EXEC_CONTROL, sec_exec_ctl); + vmx_msr = (uint32)rdmsr(X86_MSR_IA32_VMX_PROCBASED_CTLS2); + vmx_msr |= SECONDARY_EXEC_ENABLE_EPT; + vmwrite(VMCS_SECONDARY_VM_EXEC_CONTROL, vmx_msr); // Read and write Primary Processor-Based controls from TRUE MSR. // We also add the bit to enable the secondary controls. |
