diff options
| author | Alexander Potapenko <glider@google.com> | 2025-07-23 13:57:42 +0200 |
|---|---|---|
| committer | Alexander Potapenko <glider@google.com> | 2025-07-24 12:46:04 +0000 |
| commit | c76c0ee772387ce764344e75570062c4219bf495 (patch) | |
| tree | d3531688dc37e6c06fbc89cf3fa557de86ba151a /executor/common_kvm_amd64_syzos.h | |
| parent | 925dbff34225cb5d2677b079aa2db86719ec10fc (diff) | |
executor: sys/linux/dev_kvm_amd64.txt: implement rdmsr/wrmsr
Let SYZOS execute RDMSR and WRMSR on x86.
Diffstat (limited to 'executor/common_kvm_amd64_syzos.h')
| -rw-r--r-- | executor/common_kvm_amd64_syzos.h | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/executor/common_kvm_amd64_syzos.h b/executor/common_kvm_amd64_syzos.h index 64f50dfcd..22c00b501 100644 --- a/executor/common_kvm_amd64_syzos.h +++ b/executor/common_kvm_amd64_syzos.h @@ -26,6 +26,8 @@ typedef enum { SYZOS_API_UEXIT = 0, SYZOS_API_CODE = 10, SYZOS_API_CPUID = 20, + SYZOS_API_WRMSR = 30, + SYZOS_API_RDMSR = 50, SYZOS_API_STOP, // Must be the last one } syzos_api_id; @@ -50,9 +52,21 @@ struct api_call_cpuid { uint32 ecx; }; +struct api_call_1 { + struct api_call_header header; + uint64 arg; +}; + +struct api_call_2 { + struct api_call_header header; + uint64 args[2]; +}; + static void guest_uexit(uint64 exit_code); static void guest_execute_code(uint8* insns, uint64 size); static void guest_cpuid(uint32 eax, uint32 ecx); +static void guest_wrmsr(uint64 reg, uint64 val); +static void guest_rdmsr(uint64 reg); typedef enum { UEXIT_END = (uint64)-1, @@ -90,6 +104,16 @@ guest_main(uint64 size, uint64 cpu) guest_cpuid(ccmd->eax, ccmd->ecx); break; } + case SYZOS_API_WRMSR: { + struct api_call_2* ccmd = (struct api_call_2*)cmd; + guest_wrmsr(ccmd->args[0], ccmd->args[1]); + break; + } + case SYZOS_API_RDMSR: { + struct api_call_1* ccmd = (struct api_call_1*)cmd; + guest_rdmsr(ccmd->arg); + break; + } } addr += cmd->size; size -= cmd->size; @@ -120,3 +144,33 @@ GUEST_CODE static noinline void guest_cpuid(uint32 eax, uint32 ecx) : "a"(eax), "c"(ecx) : "rbx", "rdx"); } + +// Write val into an MSR register reg. +GUEST_CODE static noinline void guest_wrmsr(uint64 reg, uint64 val) +{ + // The wrmsr instruction takes its arguments in specific registers: + // edx:eax contains the 64-bit value to write, ecx contains the MSR address. + asm volatile( + "wrmsr" + : + : "c"(reg), + "a"((uint32)val), + "d"((uint32)(val >> 32)) + : "memory"); +} + +// Read an MSR register, ignore the result. +GUEST_CODE static noinline void guest_rdmsr(uint64 reg) +{ + uint32 low = 0, high = 0; + // The rdmsr instruction takes the MSR address in ecx. + // It puts the lower 32 bits of the MSR value into eax, and the upper. + // 32 bits of the MSR value into edx. + asm volatile( + "rdmsr" + : "=a"(low), + "=d"(high) + : "c"(reg) + : // No explicit clobbers. + ); +} |
