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 /arch/x86/kvm/vmx.c | |
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>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-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)) |