forked from SamuelTulach/BetterTiming
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtiming.patch
More file actions
176 lines (162 loc) · 5.67 KB
/
timing.patch
File metadata and controls
176 lines (162 loc) · 5.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 974d64bf0..ae0e8e4e9 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -2201,6 +2201,7 @@ int kvm_emulate_halt(struct kvm_vcpu *vcpu);
int kvm_emulate_halt_noskip(struct kvm_vcpu *vcpu);
int kvm_emulate_ap_reset_hold(struct kvm_vcpu *vcpu);
int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu);
+int kvm_emulate_rdtsc(struct kvm_vcpu *vcpu);
void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
void kvm_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 52524e0ca..4f1fa7c89 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -2089,6 +2089,7 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_cpuid);
int kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
{
+ vcpu->run->exit_reason = 123;
u32 eax, ebx, ecx, edx;
if (cpuid_fault_enabled(vcpu) && !kvm_require_cpl(vcpu, 0))
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index f2fa69dd5..b78c9bd3a 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -1078,6 +1078,7 @@ static void init_vmcb(struct kvm_vcpu *vcpu, bool init_event)
svm_set_intercept(svm, INTERCEPT_XSETBV);
svm_set_intercept(svm, INTERCEPT_RDPRU);
svm_set_intercept(svm, INTERCEPT_RSM);
+ svm_set_intercept(svm, INTERCEPT_RDTSC);
if (!kvm_mwait_in_guest(vcpu->kvm)) {
svm_set_intercept(svm, INTERCEPT_MONITOR);
@@ -3223,6 +3224,7 @@ static int (*const svm_exit_handlers[])(struct kvm_vcpu *vcpu) = {
[SVM_EXIT_RSM] = rsm_interception,
[SVM_EXIT_AVIC_INCOMPLETE_IPI] = avic_incomplete_ipi_interception,
[SVM_EXIT_AVIC_UNACCELERATED_ACCESS] = avic_unaccelerated_access_interception,
+ [SVM_EXIT_RDTSC] = kvm_emulate_rdtsc,
#ifdef CONFIG_KVM_AMD_SEV
[SVM_EXIT_VMGEXIT] = sev_handle_vmgexit,
#endif
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e6f2e34ec..1b4b3f6c7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1308,6 +1308,7 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(__kvm_set_xcr);
int kvm_emulate_xsetbv(struct kvm_vcpu *vcpu)
{
/* Note, #UD due to CR4.OSXSAVE=0 has priority over the intercept. */
+ vcpu->run->exit_reason = 123;
if (kvm_x86_call(get_cpl)(vcpu) != 0 ||
__kvm_set_xcr(vcpu, kvm_rcx_read(vcpu), kvm_read_edx_eax(vcpu))) {
kvm_inject_gp(vcpu, 0);
@@ -2208,6 +2209,7 @@ int kvm_emulate_as_nop(struct kvm_vcpu *vcpu)
int kvm_emulate_invd(struct kvm_vcpu *vcpu)
{
+ vcpu->run->exit_reason = 123;
/* Treat an INVD instruction as a NOP and just skip it. */
return kvm_emulate_as_nop(vcpu);
}
@@ -4379,6 +4381,9 @@ static int get_msr_mce(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata, bool host)
int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
{
+ u64 differece;
+ u64 final_time;
+
switch (msr_info->index) {
case MSR_IA32_PLATFORM_ID:
case MSR_IA32_EBL_CR_POWERON:
@@ -4445,17 +4450,10 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
* return L1's TSC value to ensure backwards-compatible
* behavior for migration.
*/
- u64 offset, ratio;
-
- if (msr_info->host_initiated) {
- offset = vcpu->arch.l1_tsc_offset;
- ratio = vcpu->arch.l1_tsc_scaling_ratio;
- } else {
- offset = vcpu->arch.tsc_offset;
- ratio = vcpu->arch.tsc_scaling_ratio;
- }
+ differece = rdtsc() - vcpu->last_exit_start;
+ final_time = vcpu->total_exit_time + differece;
- msr_info->data = kvm_scale_tsc(rdtsc(), ratio) + offset;
+ msr_info->data = rdtsc() - final_time;
break;
}
case MSR_IA32_CR_PAT:
@@ -8496,6 +8494,7 @@ static void emulator_invlpg(struct x86_emulate_ctxt *ctxt, ulong address)
static int kvm_emulate_wbinvd_noskip(struct kvm_vcpu *vcpu)
{
+ vcpu->run->exit_reason = 123;
if (!need_emulate_wbinvd(vcpu))
return X86EMUL_CONTINUE;
@@ -8518,7 +8517,24 @@ int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_emulate_wbinvd);
+int kvm_emulate_rdtsc(struct kvm_vcpu *vcpu)
+{
+ u64 differece;
+ u64 final_time;
+ u64 data;
+
+ differece = rdtsc() - vcpu->last_exit_start;
+ final_time = vcpu->total_exit_time + differece;
+
+ data = rdtsc() - final_time;
+ vcpu->arch.regs[VCPU_REGS_RAX] = data & -1u;
+ vcpu->arch.regs[VCPU_REGS_RDX] = (data >> 32) & -1u;
+
+ vcpu->run->exit_reason = 123;
+ return kvm_skip_emulated_instruction(vcpu);
+}
+EXPORT_SYMBOL_GPL(kvm_emulate_rdtsc);
static void emulator_wbinvd(struct x86_emulate_ctxt *ctxt)
{
@@ -11046,7 +11062,7 @@ static void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu)
* exiting to the userspace. Otherwise, the value will be returned to the
* userspace.
*/
-static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
+static int vcpu_enter_guest_real(struct kvm_vcpu *vcpu)
{
int r;
bool req_int_win =
@@ -11484,6 +11500,24 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
return r;
}
+static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
+{
+ int result;
+ u64 difference;
+
+ vcpu->last_exit_start = rdtsc();
+
+ result = vcpu_enter_guest_real(vcpu);
+
+ if (vcpu->run->exit_reason == 123)
+ {
+ difference = rdtsc() - vcpu->last_exit_start;
+ vcpu->total_exit_time += difference;
+ }
+
+ return result;
+}
+
static bool kvm_vcpu_running(struct kvm_vcpu *vcpu)
{
return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 5bd76cf39..7d2715f82 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -352,6 +352,9 @@ struct kvm_vcpu {
unsigned int halt_poll_ns;
bool valid_wakeup;
+ u64 last_exit_start;
+ u64 total_exit_time;
+
#ifdef CONFIG_HAS_IOMEM
int mmio_needed;
int mmio_read_completed;