Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions executor/common_kvm_amd64_syzos.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ typedef enum {
SYZOS_API_NESTED_AMD_CLGI = 383,
SYZOS_API_NESTED_AMD_INJECT_EVENT = 384,
SYZOS_API_NESTED_AMD_SET_INTERCEPT = 385,
SYZOS_API_NESTED_AMD_VMLOAD = 386,
SYZOS_API_NESTED_AMD_VMSAVE = 387,
SYZOS_API_STOP, // Must be the last one
} syzos_api_id;

Expand Down Expand Up @@ -123,6 +125,8 @@ GUEST_CODE static void guest_handle_nested_amd_stgi();
GUEST_CODE static void guest_handle_nested_amd_clgi();
GUEST_CODE static void guest_handle_nested_amd_inject_event(struct api_call_5* cmd, uint64 cpu_id);
GUEST_CODE static void guest_handle_nested_amd_set_intercept(struct api_call_5* cmd, uint64 cpu_id);
GUEST_CODE static void guest_handle_nested_amd_vmload(struct api_call_1* cmd, uint64 cpu_id);
GUEST_CODE static void guest_handle_nested_amd_vmsave(struct api_call_1* cmd, uint64 cpu_id);

typedef enum {
UEXIT_END = (uint64)-1,
Expand Down Expand Up @@ -253,6 +257,12 @@ guest_main(uint64 size, uint64 cpu)
} else if (call == SYZOS_API_NESTED_AMD_SET_INTERCEPT) {
// Set/Clear specific intercept bits in the VMCB.
guest_handle_nested_amd_set_intercept((struct api_call_5*)cmd, cpu);
} else if (call == SYZOS_API_NESTED_AMD_VMLOAD) {
// Execute VMLOAD to load state from VMCB.
guest_handle_nested_amd_vmload((struct api_call_1*)cmd, cpu);
} else if (call == SYZOS_API_NESTED_AMD_VMSAVE) {
// Execute VMSAVE to save state to VMCB.
guest_handle_nested_amd_vmsave((struct api_call_1*)cmd, cpu);
}
addr += cmd->size;
size -= cmd->size;
Expand Down Expand Up @@ -1392,4 +1402,26 @@ guest_handle_nested_amd_set_intercept(struct api_call_5* cmd, uint64 cpu_id)
vmcb_write32(vmcb_addr, (uint16)offset, current);
}

GUEST_CODE static noinline void
guest_handle_nested_amd_vmload(struct api_call_1* cmd, uint64 cpu_id)
{
if (get_cpu_vendor() != CPU_VENDOR_AMD)
return;
uint64 vm_id = cmd->arg;
uint64 vmcb_pa = X86_SYZOS_ADDR_VMCS_VMCB(cpu_id, vm_id);

asm volatile("vmload %%rax" ::"a"(vmcb_pa) : "memory");
}

GUEST_CODE static noinline void
guest_handle_nested_amd_vmsave(struct api_call_1* cmd, uint64 cpu_id)
{
if (get_cpu_vendor() != CPU_VENDOR_AMD)
return;
uint64 vm_id = cmd->arg;
uint64 vmcb_pa = X86_SYZOS_ADDR_VMCS_VMCB(cpu_id, vm_id);

asm volatile("vmsave %%rax" ::"a"(vmcb_pa) : "memory");
}

#endif // EXECUTOR_COMMON_KVM_AMD64_SYZOS_H
2 changes: 2 additions & 0 deletions sys/linux/dev_kvm_amd64.txt
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,8 @@ syzos_api_call$x86 [
nested_amd_clgi syzos_api$x86[383, void]
nested_amd_inject_event syzos_api$x86[384, syzos_api_nested_amd_inject_event]
nested_amd_set_intercept syzos_api$x86[385, syzos_api_nested_amd_set_intercept]
nested_amd_vmload syzos_api$x86[386, syzos_api_vm_id]
nested_amd_vmsave syzos_api$x86[387, syzos_api_vm_id]
] [varlen]

kvm_text_x86 [
Expand Down
11 changes: 11 additions & 0 deletions sys/linux/test/amd64-syz_kvm_nested_vmload_vmsave
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#
# requires: arch=amd64 -threaded
#

# VMLOAD/VMSAVE Reproducer
#
r0 = openat$kvm(0xffffffffffffff9c, &AUTO='/dev/kvm\x00', 0x0, 0x0)
r1 = ioctl$KVM_CREATE_VM(r0, 0x0, 0x0)
r2 = syz_kvm_setup_syzos_vm$x86(r1, &(0x7f0000000000/0x400000)=nil)
r3 = syz_kvm_add_vcpu$x86(r2, &AUTO={0x0, &AUTO=[@enable_nested={0x12c, 0x18, 0x0}, @nested_create_vm={0x12d, 0x18, 0x1}, @nested_amd_vmsave={0x183, 0x18, 0x1}, @nested_amd_vmload={0x182, 0x18, 0x1}], 0x0})
ioctl$KVM_RUN(r3, 0x0, 0x0)
Loading