diff options
-rw-r--r-- | arch/x86/kvm/svm.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index bf5799dc4f9f..c17404add91f 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -2059,10 +2059,14 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) | |||
2059 | 2059 | ||
2060 | switch (ecx) { | 2060 | switch (ecx) { |
2061 | case MSR_IA32_TSC: { | 2061 | case MSR_IA32_TSC: { |
2062 | u64 tsc; | 2062 | u64 tsc_offset; |
2063 | 2063 | ||
2064 | rdtscll(tsc); | 2064 | if (is_nested(svm)) |
2065 | *data = svm->vmcb->control.tsc_offset + tsc; | 2065 | tsc_offset = svm->nested.hsave->control.tsc_offset; |
2066 | else | ||
2067 | tsc_offset = svm->vmcb->control.tsc_offset; | ||
2068 | |||
2069 | *data = tsc_offset + native_read_tsc(); | ||
2066 | break; | 2070 | break; |
2067 | } | 2071 | } |
2068 | case MSR_K6_STAR: | 2072 | case MSR_K6_STAR: |
@@ -2148,10 +2152,17 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) | |||
2148 | 2152 | ||
2149 | switch (ecx) { | 2153 | switch (ecx) { |
2150 | case MSR_IA32_TSC: { | 2154 | case MSR_IA32_TSC: { |
2151 | u64 tsc; | 2155 | u64 tsc_offset = data - native_read_tsc(); |
2156 | u64 g_tsc_offset = 0; | ||
2157 | |||
2158 | if (is_nested(svm)) { | ||
2159 | g_tsc_offset = svm->vmcb->control.tsc_offset - | ||
2160 | svm->nested.hsave->control.tsc_offset; | ||
2161 | svm->nested.hsave->control.tsc_offset = tsc_offset; | ||
2162 | } | ||
2163 | |||
2164 | svm->vmcb->control.tsc_offset = tsc_offset + g_tsc_offset; | ||
2152 | 2165 | ||
2153 | rdtscll(tsc); | ||
2154 | svm->vmcb->control.tsc_offset = data - tsc; | ||
2155 | break; | 2166 | break; |
2156 | } | 2167 | } |
2157 | case MSR_K6_STAR: | 2168 | case MSR_K6_STAR: |