x86: Fix write_msr() casting
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 28 Apr 2016 16:42:24 +0000 (12:42 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 2 May 2016 21:11:15 +0000 (17:11 -0400)
The hardware is supposed to ignore the upper 32 bits of rdx and rax, which
it does.  But we shouldn't pass in garbage.

Here's the asm before, with the input value in rax:

# ecx previously loaded
mov    %rax,%rdx  # u64 rax has the val, putting the upper 32 in rdx
shr    $0x20,%rdx  # upper 32 in rdx
wrmsr  # rax still has the upper bits

Here's the new asm:

mov    %rax,%rdx
mov    %edi,%ecx
mov    %eax,%eax  # zeroes the upper part of rax
shr    $0x20,%rdx  # upper 32 in rdx
wrmsr

When the compiler saw the u32 cast, it just ignores the masking.  However,
the inline asm actually takes rax, not eax.  So it's wrong to cast to a u32
there.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/arch/x86/x86.h

index 5a9364f..81fa735 100644 (file)
@@ -451,9 +451,7 @@ static inline uint64_t read_msr(uint32_t reg)
 
 static inline void write_msr(uint32_t reg, uint64_t val)
 {
-       asm volatile("wrmsr" : : "d"((uint32_t)(val >> 32)),
-                                "a"((uint32_t)(val & 0xFFFFFFFF)),
-                                "c"(reg));
+       asm volatile("wrmsr" : : "d"(val >> 32), "a"(val & 0xFFFFFFFF), "c"(reg));
 }
 
 static inline void write_mmreg32(uintptr_t reg, uint32_t val)