Page 1 of 1

inline assembly: write MSR

Posted: Tue Jan 19, 2016 10:32 am
by songziming
Hi, I use this code as a helper function to write MSR:

Code: Select all

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: Select all

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?

Re: inline assembly: write MSR

Posted: Tue Jan 19, 2016 10:48 am
by xenos
Did you check and compare the generated assembly output?

Re: inline assembly: write MSR

Posted: Tue Jan 19, 2016 4:32 pm
by jnc100
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.