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 | |
| 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>
| -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: |
