diff options
author | Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp> | 2010-02-18 05:15:00 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2010-03-01 10:36:13 -0500 |
commit | 6f550484a15ea1b468665cdf59f020bf08ccb292 (patch) | |
tree | d4088b1aa157dca4dadc2a99969299dc46098148 /arch | |
parent | 8b9f44140bc4afd2698413cd9960c3912168ee91 (diff) |
KVM: Fix load_guest_segment_descriptor() to inject page fault
This patch injects page fault when reading descriptor in
load_guest_segment_descriptor() fails with FAULT.
Effects of this injection: This function is used by
kvm_load_segment_descriptor() which is necessary for the
following instructions:
- mov seg,r/m16
- jmp far
- pop ?s
This patch makes it possible to emulate the page faults
generated by these instructions. But be sure that unless
we change the kvm_load_segment_descriptor()'s ret value
propagation this patch has no effect.
Signed-off-by: Takuya Yoshikawa <yoshikawa.takuya@oss.ntt.co.jp>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kvm/x86.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f6ae4875d9d..203ee7d0ed5 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -4713,6 +4713,9 @@ static int load_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, | |||
4713 | { | 4713 | { |
4714 | struct descriptor_table dtable; | 4714 | struct descriptor_table dtable; |
4715 | u16 index = selector >> 3; | 4715 | u16 index = selector >> 3; |
4716 | int ret; | ||
4717 | u32 err; | ||
4718 | gva_t addr; | ||
4716 | 4719 | ||
4717 | get_segment_descriptor_dtable(vcpu, selector, &dtable); | 4720 | get_segment_descriptor_dtable(vcpu, selector, &dtable); |
4718 | 4721 | ||
@@ -4720,9 +4723,13 @@ static int load_guest_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, | |||
4720 | kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc); | 4723 | kvm_queue_exception_e(vcpu, GP_VECTOR, selector & 0xfffc); |
4721 | return X86EMUL_PROPAGATE_FAULT; | 4724 | return X86EMUL_PROPAGATE_FAULT; |
4722 | } | 4725 | } |
4723 | return kvm_read_guest_virt_system(dtable.base + index*8, | 4726 | addr = dtable.base + index * 8; |
4724 | seg_desc, sizeof(*seg_desc), | 4727 | ret = kvm_read_guest_virt_system(addr, seg_desc, sizeof(*seg_desc), |
4725 | vcpu, NULL); | 4728 | vcpu, &err); |
4729 | if (ret == X86EMUL_PROPAGATE_FAULT) | ||
4730 | kvm_inject_page_fault(vcpu, addr, err); | ||
4731 | |||
4732 | return ret; | ||
4726 | } | 4733 | } |
4727 | 4734 | ||
4728 | /* allowed just for 8 bytes segments */ | 4735 | /* allowed just for 8 bytes segments */ |