Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=653e3108b7d6097d25089d25ab4e99bc58b28962
Commit:     653e3108b7d6097d25089d25ab4e99bc58b28962
Parent:     eff708bc2bacd4f22cf844871341bef341bd096a
Author:     Avi Kivity <[EMAIL PROTECTED]>
AuthorDate: Mon May 7 10:55:37 2007 +0300
Committer:  Avi Kivity <[EMAIL PROTECTED]>
CommitDate: Mon Jul 16 12:05:41 2007 +0300

    KVM: Avoid corrupting tr in real mode
    
    The real mode tr needs to be set to a specific tss so that I/O
    instructions can function.  Divert the new tr values to the real
    mode save area from where they will be restored on transition to
    protected mode.
    
    This fixes some crashes on reboot when the bios accesses an I/O
    instruction.
    
    Signed-off-by: Avi Kivity <[EMAIL PROTECTED]>
---
 drivers/kvm/vmx.c |   45 +++++++++++++++++++++++++++++++--------------
 1 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index b353eaa..e39ebe0 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -1042,23 +1042,11 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu,
        var->unusable = (ar >> 16) & 1;
 }
 
-static void vmx_set_segment(struct kvm_vcpu *vcpu,
-                           struct kvm_segment *var, int seg)
+static u32 vmx_segment_access_rights(struct kvm_segment *var)
 {
-       struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
        u32 ar;
 
-       vmcs_writel(sf->base, var->base);
-       vmcs_write32(sf->limit, var->limit);
-       vmcs_write16(sf->selector, var->selector);
-       if (vcpu->rmode.active && var->s) {
-               /*
-                * Hack real-mode segments into vm86 compatibility.
-                */
-               if (var->base == 0xffff0000 && var->selector == 0xf000)
-                       vmcs_writel(sf->base, 0xf0000);
-               ar = 0xf3;
-       } else if (var->unusable)
+       if (var->unusable)
                ar = 1 << 16;
        else {
                ar = var->type & 15;
@@ -1072,6 +1060,35 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,
        }
        if (ar == 0) /* a 0 value means unusable */
                ar = AR_UNUSABLE_MASK;
+
+       return ar;
+}
+
+static void vmx_set_segment(struct kvm_vcpu *vcpu,
+                           struct kvm_segment *var, int seg)
+{
+       struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+       u32 ar;
+
+       if (vcpu->rmode.active && seg == VCPU_SREG_TR) {
+               vcpu->rmode.tr.selector = var->selector;
+               vcpu->rmode.tr.base = var->base;
+               vcpu->rmode.tr.limit = var->limit;
+               vcpu->rmode.tr.ar = vmx_segment_access_rights(var);
+               return;
+       }
+       vmcs_writel(sf->base, var->base);
+       vmcs_write32(sf->limit, var->limit);
+       vmcs_write16(sf->selector, var->selector);
+       if (vcpu->rmode.active && var->s) {
+               /*
+                * Hack real-mode segments into vm86 compatibility.
+                */
+               if (var->base == 0xffff0000 && var->selector == 0xf000)
+                       vmcs_writel(sf->base, 0xf0000);
+               ar = 0xf3;
+       } else
+               ar = vmx_segment_access_rights(var);
        vmcs_write32(sf->ar_bytes, ar);
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to