diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2009-09-16 09:24:18 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-10-04 07:57:23 -0400 |
commit | 20824f30bb0b8ae0a4099895fd4509f54cf2e1e2 (patch) | |
tree | 253c30ec098720c1c2ac69f3bd38967c02d26b7b /arch/x86/kvm/svm.c | |
parent | 77b1ab1732feb5e3dcbaf31d2f7547c5229f5f3a (diff) |
KVM: SVM: Handle tsc in svm_get_msr/svm_set_msr correctly
When running nested we need to touch the l1 guests
tsc_offset. Otherwise changes will be lost or a wrong value
be read.
Cc: stable@kernel.org
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/svm.c')
-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: |