diff options
-rw-r--r-- | arch/x86/kvm/svm.c | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 2ae94b540358..74f89f0b9e3f 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -192,6 +192,26 @@ static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu) | |||
192 | return container_of(vcpu, struct vcpu_svm, vcpu); | 192 | return container_of(vcpu, struct vcpu_svm, vcpu); |
193 | } | 193 | } |
194 | 194 | ||
195 | static void recalc_intercepts(struct vcpu_svm *svm) | ||
196 | { | ||
197 | struct vmcb_control_area *c, *h; | ||
198 | struct nested_state *g; | ||
199 | |||
200 | if (!is_guest_mode(&svm->vcpu)) | ||
201 | return; | ||
202 | |||
203 | c = &svm->vmcb->control; | ||
204 | h = &svm->nested.hsave->control; | ||
205 | g = &svm->nested; | ||
206 | |||
207 | c->intercept_cr_read = h->intercept_cr_read | g->intercept_cr_read; | ||
208 | c->intercept_cr_write = h->intercept_cr_write | g->intercept_cr_write; | ||
209 | c->intercept_dr_read = h->intercept_dr_read | g->intercept_dr_read; | ||
210 | c->intercept_dr_write = h->intercept_dr_write | g->intercept_dr_write; | ||
211 | c->intercept_exceptions = h->intercept_exceptions | g->intercept_exceptions; | ||
212 | c->intercept = h->intercept | g->intercept; | ||
213 | } | ||
214 | |||
195 | static inline void enable_gif(struct vcpu_svm *svm) | 215 | static inline void enable_gif(struct vcpu_svm *svm) |
196 | { | 216 | { |
197 | svm->vcpu.arch.hflags |= HF_GIF_MASK; | 217 | svm->vcpu.arch.hflags |= HF_GIF_MASK; |
@@ -2273,23 +2293,6 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm) | |||
2273 | /* We don't want to see VMMCALLs from a nested guest */ | 2293 | /* We don't want to see VMMCALLs from a nested guest */ |
2274 | svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMMCALL); | 2294 | svm->vmcb->control.intercept &= ~(1ULL << INTERCEPT_VMMCALL); |
2275 | 2295 | ||
2276 | /* | ||
2277 | * We don't want a nested guest to be more powerful than the guest, so | ||
2278 | * all intercepts are ORed | ||
2279 | */ | ||
2280 | svm->vmcb->control.intercept_cr_read |= | ||
2281 | nested_vmcb->control.intercept_cr_read; | ||
2282 | svm->vmcb->control.intercept_cr_write |= | ||
2283 | nested_vmcb->control.intercept_cr_write; | ||
2284 | svm->vmcb->control.intercept_dr_read |= | ||
2285 | nested_vmcb->control.intercept_dr_read; | ||
2286 | svm->vmcb->control.intercept_dr_write |= | ||
2287 | nested_vmcb->control.intercept_dr_write; | ||
2288 | svm->vmcb->control.intercept_exceptions |= | ||
2289 | nested_vmcb->control.intercept_exceptions; | ||
2290 | |||
2291 | svm->vmcb->control.intercept |= nested_vmcb->control.intercept; | ||
2292 | |||
2293 | svm->vmcb->control.lbr_ctl = nested_vmcb->control.lbr_ctl; | 2296 | svm->vmcb->control.lbr_ctl = nested_vmcb->control.lbr_ctl; |
2294 | svm->vmcb->control.int_vector = nested_vmcb->control.int_vector; | 2297 | svm->vmcb->control.int_vector = nested_vmcb->control.int_vector; |
2295 | svm->vmcb->control.int_state = nested_vmcb->control.int_state; | 2298 | svm->vmcb->control.int_state = nested_vmcb->control.int_state; |
@@ -2302,6 +2305,12 @@ static bool nested_svm_vmrun(struct vcpu_svm *svm) | |||
2302 | /* Enter Guest-Mode */ | 2305 | /* Enter Guest-Mode */ |
2303 | enter_guest_mode(&svm->vcpu); | 2306 | enter_guest_mode(&svm->vcpu); |
2304 | 2307 | ||
2308 | /* | ||
2309 | * Merge guest and host intercepts - must be called with vcpu in | ||
2310 | * guest-mode to take affect here | ||
2311 | */ | ||
2312 | recalc_intercepts(svm); | ||
2313 | |||
2305 | svm->nested.vmcb = vmcb_gpa; | 2314 | svm->nested.vmcb = vmcb_gpa; |
2306 | 2315 | ||
2307 | enable_gif(svm); | 2316 | enable_gif(svm); |