Skip to content

Commit 9632370

Browse files
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.
1 parent 35fd579 commit 9632370

File tree

1 file changed

+21
-37
lines changed

1 file changed

+21
-37
lines changed

executor/common_kvm_amd64_syzos.h

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,8 @@ GUEST_CODE static noinline void guest_handle_cpuid(uint32 eax, uint32 ecx)
249249
: "rbx", "rdx");
250250
}
251251

252-
// Write val into an MSR register reg.
253-
GUEST_CODE static noinline void guest_handle_wrmsr(uint64 reg, uint64 val)
252+
GUEST_CODE static noinline void wrmsr(uint64 reg, uint64 val)
254253
{
255-
// The wrmsr instruction takes its arguments in specific registers:
256-
// edx:eax contains the 64-bit value to write, ecx contains the MSR address.
257254
asm volatile(
258255
"wrmsr"
259256
:
@@ -263,20 +260,26 @@ GUEST_CODE static noinline void guest_handle_wrmsr(uint64 reg, uint64 val)
263260
: "memory");
264261
}
265262

266-
// Read an MSR register, ignore the result.
267-
GUEST_CODE static noinline void guest_handle_rdmsr(uint64 reg)
263+
// Write val into an MSR register reg.
264+
GUEST_CODE static noinline void guest_handle_wrmsr(uint64 reg, uint64 val)
268265
{
269-
uint32 low = 0, high = 0;
270-
// The rdmsr instruction takes the MSR address in ecx.
266+
wrmsr(reg, val);
267+
}
268+
269+
GUEST_CODE static noinline uint64 rdmsr(uint64 msr_id)
270+
{
271+
uint32 low, high;
272+
// The RDMSR instruction takes the MSR address in ecx.
271273
// It puts the lower 32 bits of the MSR value into eax, and the upper.
272274
// 32 bits of the MSR value into edx.
273-
asm volatile(
274-
"rdmsr"
275-
: "=a"(low),
276-
"=d"(high)
277-
: "c"(reg)
278-
: // No explicit clobbers.
279-
);
275+
asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr_id));
276+
return ((uint64)high << 32) | low;
277+
}
278+
279+
// Read an MSR register, ignore the result.
280+
GUEST_CODE static noinline void guest_handle_rdmsr(uint64 reg)
281+
{
282+
(void)rdmsr(reg);
280283
}
281284

282285
// Write to CRn control register.
@@ -488,24 +491,6 @@ GUEST_CODE static inline void write_cr4(uint64 val)
488491
asm volatile("mov %0, %%cr4" : : "r"(val));
489492
}
490493

491-
GUEST_CODE static noinline void wrmsr(uint64 reg, uint64 val)
492-
{
493-
asm volatile(
494-
"wrmsr"
495-
:
496-
: "c"(reg),
497-
"a"((uint32)val),
498-
"d"((uint32)(val >> 32))
499-
: "memory");
500-
}
501-
502-
GUEST_CODE static noinline uint64 rdmsr(uint32 msr_id)
503-
{
504-
uint64 msr_value;
505-
asm volatile("rdmsr" : "=A"(msr_value) : "c"(msr_id));
506-
return msr_value;
507-
}
508-
509494
GUEST_CODE static noinline void vmwrite(uint64 field, uint64 value)
510495
{
511496
uint8 error = 0; // nolint
@@ -678,10 +663,9 @@ GUEST_CODE static noinline void init_vmcs_control_fields(uint64 cpu_id, uint64 v
678663
vmwrite(VMCS_PIN_BASED_VM_EXEC_CONTROL, (uint32)vmx_msr);
679664

680665
// Setup Secondary Processor-Based controls: enable EPT.
681-
vmx_msr = rdmsr(X86_MSR_IA32_VMX_PROCBASED_CTLS2);
682-
uint32 sec_exec_ctl = (uint32)(vmx_msr >> 32); // Must-be-1 bits.
683-
sec_exec_ctl |= ((uint32)vmx_msr & SECONDARY_EXEC_ENABLE_EPT); // Allowed bits.
684-
vmwrite(VMCS_SECONDARY_VM_EXEC_CONTROL, sec_exec_ctl);
666+
vmx_msr = (uint32)rdmsr(X86_MSR_IA32_VMX_PROCBASED_CTLS2);
667+
vmx_msr |= SECONDARY_EXEC_ENABLE_EPT;
668+
vmwrite(VMCS_SECONDARY_VM_EXEC_CONTROL, vmx_msr);
685669

686670
// Read and write Primary Processor-Based controls from TRUE MSR.
687671
// We also add the bit to enable the secondary controls.

0 commit comments

Comments
 (0)