OSDev.org
https://forum.osdev.org/

inline assembly: write MSR
https://forum.osdev.org/viewtopic.php?f=1&t=30001
Page 1 of 1

Author:  songziming [ Tue Jan 19, 2016 10:32 am ]
Post subject:  inline assembly: write MSR

Hi, I use this code as a helper function to write MSR:

Code:
static inline void write_msr(uint32_t msr_id, uint64_t msr_val) {
    __asm__ __volatile__("wrmsr" :: "c"(msr_id), "A"(msr_val));
}


The key is "A" notation, which stands for "edx:eax" according to GCC manual. However, "write_msr" works well under QEMU, but always fail under Bochs.

So I changed the function to this:

Code:
static inline void write_msr(uint32_t msr_id, uint64_t msr_val) {
    uint32_t edx = msr_val >> 32;
    uint32_t eax = msr_val & 0xffffffff;
    __asm__ __volatile__("wrmsr" :: "c"(msr_id), "d"(edx), "a"(eax));
}


And both QEMU and Bochs runs well. But I can't understand the reason.

PS. My OS is 64 bit, does it matters?

Author:  xenos [ Tue Jan 19, 2016 10:48 am ]
Post subject:  Re: inline assembly: write MSR

Did you check and compare the generated assembly output?

Author:  jnc100 [ Tue Jan 19, 2016 4:32 pm ]
Post subject:  Re: inline assembly: write MSR

songziming wrote:
PS. My OS is 64 bit, does it matters?
Yes. On x86_64 gcc will only split a 128 bit value between rax and rdx using the "A" constraint. For the 64-bit value you are using, it is free to pick either rax or rdx. If you compile as 32 bit is should split a 64 bit value to eax:edx.

In other words, doing it with the manual splitting as you are doing is the only way.

I cannot explain why it worked on qemu the first way.

Regards,
John.

Page 1 of 1 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/