Skip to content

Commit 71648bd

Browse files
executor: sys/linux/test: handle RDTSCP in L2
Enable basic RDTSCP handling. Ensure that Intel hosts exit on RDTSCP in L2, and that both Intel and AMD can handle RDTSCP exits. Add amd64-syz_kvm_nested_vmresume-rdtscp to test that.
1 parent 9632370 commit 71648bd

File tree

3 files changed

+44
-3
lines changed

3 files changed

+44
-3
lines changed

executor/common_kvm_amd64_syzos.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ GUEST_CODE static noinline void init_vmcs_control_fields(uint64 cpu_id, uint64 v
664664

665665
// Setup Secondary Processor-Based controls: enable EPT.
666666
vmx_msr = (uint32)rdmsr(X86_MSR_IA32_VMX_PROCBASED_CTLS2);
667-
vmx_msr |= SECONDARY_EXEC_ENABLE_EPT;
667+
vmx_msr |= SECONDARY_EXEC_ENABLE_EPT | SECONDARY_EXEC_ENABLE_RDTSCP;
668668
vmwrite(VMCS_SECONDARY_VM_EXEC_CONTROL, vmx_msr);
669669

670670
// Read and write Primary Processor-Based controls from TRUE MSR.
@@ -728,6 +728,7 @@ typedef enum {
728728
SYZOS_NESTED_EXIT_REASON_INVD = 2,
729729
SYZOS_NESTED_EXIT_REASON_CPUID = 3,
730730
SYZOS_NESTED_EXIT_REASON_RDTSC = 4,
731+
SYZOS_NESTED_EXIT_REASON_RDTSCP = 5,
731732
SYZOS_NESTED_EXIT_REASON_UNKNOWN = 0xFF,
732733
} syz_nested_exit_reason;
733734

@@ -747,6 +748,7 @@ GUEST_CODE static void guest_uexit_l2(uint64 exit_reason, syz_nested_exit_reason
747748
#define EXIT_REASON_HLT 0xc
748749
#define EXIT_REASON_INVD 0xd
749750
#define EXIT_REASON_RDTSC 0x10
751+
#define EXIT_REASON_RDTSCP 0x33
750752

751753
GUEST_CODE static syz_nested_exit_reason map_intel_exit_reason(uint64 basic_reason)
752754
{
@@ -760,6 +762,8 @@ GUEST_CODE static syz_nested_exit_reason map_intel_exit_reason(uint64 basic_reas
760762
return SYZOS_NESTED_EXIT_REASON_CPUID;
761763
if (reason == EXIT_REASON_RDTSC)
762764
return SYZOS_NESTED_EXIT_REASON_RDTSC;
765+
if (reason == EXIT_REASON_RDTSCP)
766+
return SYZOS_NESTED_EXIT_REASON_RDTSCP;
763767
return SYZOS_NESTED_EXIT_REASON_UNKNOWN;
764768
}
765769

@@ -769,8 +773,11 @@ GUEST_CODE static void advance_l2_rip_intel(uint64 basic_reason)
769773
volatile uint64 reason = basic_reason;
770774
uint64 rip = vmread(VMCS_GUEST_RIP);
771775
if ((reason == EXIT_REASON_INVD) || (reason == EXIT_REASON_CPUID) ||
772-
(reason == EXIT_REASON_RDTSC))
776+
(reason == EXIT_REASON_RDTSC)) {
773777
rip += 2;
778+
} else if (reason == EXIT_REASON_RDTSCP) {
779+
rip += 3;
780+
}
774781
vmwrite(VMCS_GUEST_RIP, rip);
775782
}
776783

@@ -833,6 +840,7 @@ __attribute__((naked)) GUEST_CODE static void nested_vm_exit_handler_intel_asm(v
833840
#define VMEXIT_CPUID 0x72
834841
#define VMEXIT_INVD 0x76
835842
#define VMEXIT_HLT 0x78
843+
#define VMEXIT_RDTSCP 0x87
836844

837845
GUEST_CODE static syz_nested_exit_reason map_amd_exit_reason(uint64 basic_reason)
838846
{
@@ -846,6 +854,8 @@ GUEST_CODE static syz_nested_exit_reason map_amd_exit_reason(uint64 basic_reason
846854
return SYZOS_NESTED_EXIT_REASON_CPUID;
847855
if (reason == VMEXIT_RDTSC)
848856
return SYZOS_NESTED_EXIT_REASON_RDTSC;
857+
if (reason == VMEXIT_RDTSCP)
858+
return SYZOS_NESTED_EXIT_REASON_RDTSCP;
849859
return SYZOS_NESTED_EXIT_REASON_UNKNOWN;
850860
}
851861

@@ -856,8 +866,11 @@ GUEST_CODE static void advance_l2_rip_amd(uint64 basic_reason, uint64 cpu_id, ui
856866
uint64 vmcb_addr = X86_SYZOS_ADDR_VMCS_VMCB(cpu_id, vm_id);
857867
uint64 rip = vmcb_read64((volatile uint8*)vmcb_addr, VMCB_GUEST_RIP);
858868
if ((reason == VMEXIT_INVD) || (reason == VMEXIT_CPUID) ||
859-
(reason == VMEXIT_RDTSC))
869+
(reason == VMEXIT_RDTSC)) {
860870
rip += 2;
871+
} else if (reason == VMEXIT_RDTSCP) {
872+
rip += 3;
873+
}
861874
vmcb_write64(vmcb_addr, VMCB_GUEST_RIP, rip);
862875
}
863876

executor/kvm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@
252252
#define VMX_AR_LDTR_UNUSABLE 0x10000
253253
#define VM_ENTRY_IA32E_MODE (1U << 9)
254254
#define SECONDARY_EXEC_ENABLE_EPT (1U << 1)
255+
#define SECONDARY_EXEC_ENABLE_RDTSCP (1U << 3)
255256
#define VM_EXIT_HOST_ADDR_SPACE_SIZE (1U << 9)
256257
#define CPU_BASED_ACTIVATE_SECONDARY_CONTROLS (1U << 31)
257258

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#
2+
# requires: arch=amd64 -threaded
3+
#
4+
r0 = openat$kvm(0, &AUTO='/dev/kvm\x00', 0x0, 0x0)
5+
r1 = ioctl$KVM_CREATE_VM(r0, AUTO, 0x0)
6+
r2 = syz_kvm_setup_syzos_vm$x86(r1, &(0x7f0000c00000/0x400000)=nil)
7+
8+
# Create a nested VM that performs RDTSCP (0f 01 f9) and HLT (f4).
9+
#
10+
r3 = syz_kvm_add_vcpu$x86(r2, &AUTO={0x0, &AUTO=[@enable_nested={AUTO, AUTO, 0x0}, @nested_create_vm={AUTO, AUTO, 0x0}, @nested_load_code={AUTO, AUTO, {0x0, "0f01f9f4"}}, @nested_vmlaunch={AUTO, AUTO, 0x0}, @nested_vmresume={AUTO, AUTO, 0x0}], AUTO})
11+
r4 = ioctl$KVM_GET_VCPU_MMAP_SIZE(r0, AUTO)
12+
r5 = mmap$KVM_VCPU(&(0x7f0000009000/0x1000)=nil, r4, 0x3, 0x1, r3, 0x0)
13+
14+
# L2 VM executes CPUID. Exit reason is mapped to 0xe2e20005.
15+
#
16+
ioctl$KVM_RUN(r3, AUTO, 0x0)
17+
syz_kvm_assert_syzos_uexit$x86(r5, 0xe2e20005)
18+
19+
# L1 resumes L2, which executes HLT. Exit reason is mapped to 0xe2e20001.
20+
#
21+
ioctl$KVM_RUN(r3, AUTO, 0x0)
22+
syz_kvm_assert_syzos_uexit$x86(r5, 0xe2e20001)
23+
24+
# guest_main should finish with guest_uexit(-1).
25+
#
26+
ioctl$KVM_RUN(r3, AUTO, 0x0)
27+
syz_kvm_assert_syzos_uexit$x86(r5, 0xffffffff)

0 commit comments

Comments
 (0)