diff options
| author | Mohammed Gamal <m.gamal005@gmail.com> | 2008-08-17 09:42:16 -0400 |
|---|---|---|
| committer | Avi Kivity <avi@qumranet.com> | 2008-10-15 04:15:20 -0400 |
| commit | a89a8fb93ba63d4ad39db97c90997c409c87ccb9 (patch) | |
| tree | 36c936e5fabd15357bf9b65649ddef08a8ea22f0 | |
| parent | ea953ef0ca84e778187905177e2a789a1974837b (diff) | |
KVM: VMX: Modify mode switching and vmentry functions
This patch modifies mode switching and vmentry function in order to
drive invalid guest state emulation.
Signed-off-by: Mohammed Gamal <m.gamal005@gmail.com>
Signed-off-by: Avi Kivity <avi@qumranet.com>
| -rw-r--r-- | arch/x86/kvm/vmx.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index eae1f2c64f97..9840f37925a2 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
| @@ -1298,7 +1298,9 @@ static void fix_pmode_dataseg(int seg, struct kvm_save_segment *save) | |||
| 1298 | static void enter_pmode(struct kvm_vcpu *vcpu) | 1298 | static void enter_pmode(struct kvm_vcpu *vcpu) |
| 1299 | { | 1299 | { |
| 1300 | unsigned long flags; | 1300 | unsigned long flags; |
| 1301 | struct vcpu_vmx *vmx = to_vmx(vcpu); | ||
| 1301 | 1302 | ||
| 1303 | vmx->emulation_required = 1; | ||
| 1302 | vcpu->arch.rmode.active = 0; | 1304 | vcpu->arch.rmode.active = 0; |
| 1303 | 1305 | ||
| 1304 | vmcs_writel(GUEST_TR_BASE, vcpu->arch.rmode.tr.base); | 1306 | vmcs_writel(GUEST_TR_BASE, vcpu->arch.rmode.tr.base); |
| @@ -1315,6 +1317,9 @@ static void enter_pmode(struct kvm_vcpu *vcpu) | |||
| 1315 | 1317 | ||
| 1316 | update_exception_bitmap(vcpu); | 1318 | update_exception_bitmap(vcpu); |
| 1317 | 1319 | ||
| 1320 | if (emulate_invalid_guest_state) | ||
| 1321 | return; | ||
| 1322 | |||
| 1318 | fix_pmode_dataseg(VCPU_SREG_ES, &vcpu->arch.rmode.es); | 1323 | fix_pmode_dataseg(VCPU_SREG_ES, &vcpu->arch.rmode.es); |
| 1319 | fix_pmode_dataseg(VCPU_SREG_DS, &vcpu->arch.rmode.ds); | 1324 | fix_pmode_dataseg(VCPU_SREG_DS, &vcpu->arch.rmode.ds); |
| 1320 | fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->arch.rmode.gs); | 1325 | fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->arch.rmode.gs); |
| @@ -1355,7 +1360,9 @@ static void fix_rmode_seg(int seg, struct kvm_save_segment *save) | |||
| 1355 | static void enter_rmode(struct kvm_vcpu *vcpu) | 1360 | static void enter_rmode(struct kvm_vcpu *vcpu) |
| 1356 | { | 1361 | { |
| 1357 | unsigned long flags; | 1362 | unsigned long flags; |
| 1363 | struct vcpu_vmx *vmx = to_vmx(vcpu); | ||
| 1358 | 1364 | ||
| 1365 | vmx->emulation_required = 1; | ||
| 1359 | vcpu->arch.rmode.active = 1; | 1366 | vcpu->arch.rmode.active = 1; |
| 1360 | 1367 | ||
| 1361 | vcpu->arch.rmode.tr.base = vmcs_readl(GUEST_TR_BASE); | 1368 | vcpu->arch.rmode.tr.base = vmcs_readl(GUEST_TR_BASE); |
| @@ -1377,6 +1384,9 @@ static void enter_rmode(struct kvm_vcpu *vcpu) | |||
| 1377 | vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | X86_CR4_VME); | 1384 | vmcs_writel(GUEST_CR4, vmcs_readl(GUEST_CR4) | X86_CR4_VME); |
| 1378 | update_exception_bitmap(vcpu); | 1385 | update_exception_bitmap(vcpu); |
| 1379 | 1386 | ||
| 1387 | if (emulate_invalid_guest_state) | ||
| 1388 | goto continue_rmode; | ||
| 1389 | |||
| 1380 | vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4); | 1390 | vmcs_write16(GUEST_SS_SELECTOR, vmcs_readl(GUEST_SS_BASE) >> 4); |
| 1381 | vmcs_write32(GUEST_SS_LIMIT, 0xffff); | 1391 | vmcs_write32(GUEST_SS_LIMIT, 0xffff); |
| 1382 | vmcs_write32(GUEST_SS_AR_BYTES, 0xf3); | 1392 | vmcs_write32(GUEST_SS_AR_BYTES, 0xf3); |
| @@ -1392,6 +1402,7 @@ static void enter_rmode(struct kvm_vcpu *vcpu) | |||
| 1392 | fix_rmode_seg(VCPU_SREG_GS, &vcpu->arch.rmode.gs); | 1402 | fix_rmode_seg(VCPU_SREG_GS, &vcpu->arch.rmode.gs); |
| 1393 | fix_rmode_seg(VCPU_SREG_FS, &vcpu->arch.rmode.fs); | 1403 | fix_rmode_seg(VCPU_SREG_FS, &vcpu->arch.rmode.fs); |
| 1394 | 1404 | ||
| 1405 | continue_rmode: | ||
| 1395 | kvm_mmu_reset_context(vcpu); | 1406 | kvm_mmu_reset_context(vcpu); |
| 1396 | init_rmode(vcpu->kvm); | 1407 | init_rmode(vcpu->kvm); |
| 1397 | } | 1408 | } |
| @@ -2317,6 +2328,9 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu) | |||
| 2317 | 2328 | ||
| 2318 | ret = 0; | 2329 | ret = 0; |
| 2319 | 2330 | ||
| 2331 | /* HACK: Don't enable emulation on guest boot/reset */ | ||
| 2332 | vmx->emulation_required = 0; | ||
| 2333 | |||
| 2320 | out: | 2334 | out: |
| 2321 | up_read(&vcpu->kvm->slots_lock); | 2335 | up_read(&vcpu->kvm->slots_lock); |
| 2322 | return ret; | 2336 | return ret; |
| @@ -3190,6 +3204,12 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
| 3190 | struct vcpu_vmx *vmx = to_vmx(vcpu); | 3204 | struct vcpu_vmx *vmx = to_vmx(vcpu); |
| 3191 | u32 intr_info; | 3205 | u32 intr_info; |
| 3192 | 3206 | ||
| 3207 | /* Handle invalid guest state instead of entering VMX */ | ||
| 3208 | if (vmx->emulation_required && emulate_invalid_guest_state) { | ||
| 3209 | handle_invalid_guest_state(vcpu, kvm_run); | ||
| 3210 | return; | ||
| 3211 | } | ||
| 3212 | |||
| 3193 | if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty)) | 3213 | if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty)) |
| 3194 | vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]); | 3214 | vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]); |
| 3195 | if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty)) | 3215 | if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty)) |
