WRMSR на 64-битном регистре RCX x86_64 неправильно установлено
Я хочу записать в регистр PMC1, поэтому я хочу установить RCX на 188.
Код, который я использую для использования инструкции WRMSR, прилагается в конце. Проблема в том, что я передаю значения eax и ecx (64 бита) в макрос, но регистр%rcx всегда устанавливается в значение eax.
#define RTXEN_WRITE_MSR(eax, ecx) __asm__ __volatile__(\
"movq %0, %%rax\n\t"\
"xorq %%rdx, %%rdx\n\t"\
"xorq %%rcx, %%rcx\n\t"\
"movq %1, %%rcx\n\t"\
"wrmsr"\
:\
:"r" (eax), "r" (ecx)\
:\
)
uint64_t eax = 0x14f2e
uint64_t edx = 0x188
printk("eax:%#018lx, edx:%#018lx\n", eax, edx);
RTXEN_WRITE_MSR(eax, ecx);
Когда RTXEN_WRITE_MSR(eax, ecx) выполняется, ядро паникует! Информация о регистре выглядит следующим образом:
(XEN) CPU: 1
(XEN) RIP: e008:[<ffff82c4c02166b1>] setread_perf_counter+0x251/0x4c0
(XEN) RFLAGS: 0000000000010046 CONTEXT: hypervisor
(XEN) rax: 0000000000014f2e rbx: ffff8308558f7718 **rcx: 0000000000014f2e**
(XEN) rdx: 0000000000000000 rsi: 000000000000000a rdi: ffff82c4c0270640
(XEN) rbp: 0000000000000001 rsp: ffff83086bec7cd8 r8: 0000000000000004
(XEN) r9: 0000000000000004 r10: 0000000000000004 r11: 0000000000000400
(XEN) r12: 0000000000014f2e r13: 0000000200000000 r14: ffff83086bec7dd8
(XEN) r15: 00000000000000fb cr0: 000000008005003b cr4: 00000000001426f0
(XEN) cr3: 000000008ce6a000 cr2: ffff880115ca32a0
(XEN) ds: 002b es: 002b fs: 0000 gs: 0000 ss: e010 cs: e008
Может кто-нибудь помочь мне увидеть, что не так в моем коде?
1 ответ
Вы знаете, что ваш компилятор может передать ваши аргументы в правильные регистры сразу?
asm volatile (
"wrmsr"
:
: "a" ((uint32_t)eax)
, "c" ((uint32_t)ecx)
, "d" ((uint32_t)0)
);
Тип к uint32_t
гарантирует, что компилятор будет использовать 32-битные варианты регистров (eax
, ecx
, edx
).
Вы можете найти модификаторы ограничений для регистров Intel здесь: http://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
На заметку: если вы используете регистры в ассемблере, вам нужно сообщить компилятору, что вы делаете это. Вам нужно поместить все регистры, которые вы используете, и компилятор не знает о них в списке регистров clobber после третьего двоеточия.