Skip to content

Commit 6bc31bd

Browse files
aprzywaravikivity
authored andcommitted
KVM: SVM: implement NEXTRIPsave SVM feature
On SVM we set the instruction length of skipped instructions to hard-coded, well known values, which could be wrong when (bogus, but valid) prefixes (REX, segment override) are used. Newer AMD processors (Fam10h 45nm and better, aka. PhenomII or AthlonII) have an explicit NEXTRIP field in the VMCB containing the desired information. Since it is cheap to do so, we use this field to override the guessed value on newer processors. A fix for older CPUs would be rather expensive, as it would require to fetch and partially decode the instruction. As the problem is not a security issue and needs special, handcrafted code to trigger (no compiler will ever generate such code), I omit a fix for older CPUs. If someone is interested, I have both a patch for these CPUs as well as demo code triggering this issue: It segfaults under KVM, but runs perfectly on native Linux. Signed-off-by: Andre Przywara <[email protected]> Signed-off-by: Marcelo Tosatti <[email protected]>
1 parent f7a7119 commit 6bc31bd

File tree

2 files changed

+11
-6
lines changed

2 files changed

+11
-6
lines changed

arch/x86/include/asm/svm.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
8181
u32 event_inj_err;
8282
u64 nested_cr3;
8383
u64 lbr_ctl;
84-
u8 reserved_5[832];
84+
u64 reserved_5;
85+
u64 next_rip;
86+
u8 reserved_6[816];
8587
};
8688

8789

arch/x86/kvm/svm.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ MODULE_LICENSE("GPL");
4444
#define SEG_TYPE_LDT 2
4545
#define SEG_TYPE_BUSY_TSS16 3
4646

47-
#define SVM_FEATURE_NPT (1 << 0)
48-
#define SVM_FEATURE_LBRV (1 << 1)
49-
#define SVM_FEATURE_SVML (1 << 2)
50-
#define SVM_FEATURE_NRIP (1 << 3)
51-
#define SVM_FEATURE_PAUSE_FILTER (1 << 10)
47+
#define SVM_FEATURE_NPT (1 << 0)
48+
#define SVM_FEATURE_LBRV (1 << 1)
49+
#define SVM_FEATURE_SVML (1 << 2)
50+
#define SVM_FEATURE_NRIP (1 << 3)
51+
#define SVM_FEATURE_PAUSE_FILTER (1 << 10)
5252

5353
#define NESTED_EXIT_HOST 0 /* Exit handled on host level */
5454
#define NESTED_EXIT_DONE 1 /* Exit caused nested vmexit */
@@ -320,6 +320,9 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu)
320320
{
321321
struct vcpu_svm *svm = to_svm(vcpu);
322322

323+
if (svm->vmcb->control.next_rip != 0)
324+
svm->next_rip = svm->vmcb->control.next_rip;
325+
323326
if (!svm->next_rip) {
324327
if (emulate_instruction(vcpu, 0, 0, EMULTYPE_SKIP) !=
325328
EMULATE_DONE)

0 commit comments

Comments
 (0)