File xen-amd-v-menu-timer-issue.patch of Package kernel

Date: Wed, 25 Oct 2006 15:50:30 -0400
From: Bhavana Nagendra <bnagendr@redhat.com>
Subject: RHEL5 PATCH: AMD-V windows guest boot menu timer issue

AMD-V does not require the delaying of interrupt injection if the guest
IF_FLAG disallows interrupts.  Remove the code in svm_intr_assist()
that was checking the guest IF in eflags.

This patch fixes the problem with HVM Windows guests, with observing a
very slow timer countdown on the initial boot menu, when there is more
than one boot option.  Kbd response in this same Windows boot menu is
also acceptably responsive with this patch.

The upstream patches are in xen-unstable and applies cleanly to change 
set 11831.   I have created a single patch and it applies cleanly to 
2.6.18-1.2736.el5.  Please review and ACK for milestone 7.






--- xen/arch/x86/hvm/svm/intr.c.orig	2006-10-25 12:59:39.000000000 -0400
+++ xen/arch/x86/hvm/svm/intr.c	2006-10-25 14:21:39.000000000 -0400
@@ -43,7 +43,7 @@
  * to be suitable for SVM.
  */
 
-static inline int svm_inject_extint(struct vcpu *v, int trap, int error_code)
+static inline int svm_inject_extint(struct vcpu *v, int trap)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     vintr_t intr;
@@ -74,7 +74,6 @@ asmlinkage void svm_intr_assist(void) 
     int intr_type = APIC_DM_EXTINT;
     int intr_vector = -1;
     int re_injecting = 0;
-    unsigned long rflags;
 
     ASSERT(vmcb);
 
@@ -82,19 +81,28 @@ asmlinkage void svm_intr_assist(void) 
     /* Previous Interrupt delivery caused this Intercept? */
     if (vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0)) {
         v->arch.hvm_svm.saved_irq_vector = vmcb->exitintinfo.fields.vector;
-//           printk("Injecting PF#: saving IRQ from ExitInfo\n");
         vmcb->exitintinfo.bytes = 0;
         re_injecting = 1;
     }
 
-    /* Guest's interrputs masked? */
-    rflags = vmcb->rflags;
-    if (irq_masked(rflags)) {
-        HVM_DBG_LOG(DBG_LEVEL_1, "Guest IRQs masked: rflags: %lx", rflags);
-        /* bail out, we won't be injecting an interrupt this time */
+    /*
+     * If event requires injecting then do not inject int.
+     */
+    if (unlikely(v->arch.hvm_svm.inject_event)) {
+        v->arch.hvm_svm.inject_event = 0;
         return;
     }
-    
+
+    /*
+     * create a 'fake' virtual interrupt on to intercept as soon
+     * as the guest _can_ take interrupts
+     */
+    if (irq_masked(vmcb->rflags) || vmcb->interrupt_shadow) {
+        vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
+        svm_inject_extint(v, 0x0); /* actual vector doesn't really matter */
+        return;
+    }
+
     /* Previous interrupt still pending? */
     if (vmcb->vintr.fields.irq) {
 //        printk("Re-injecting IRQ from Vintr\n");
@@ -146,8 +154,7 @@ asmlinkage void svm_intr_assist(void) 
             }
             /* let's inject this interrupt */
             TRACE_3D(TRC_VMX_INT, v->domain->domain_id, intr_vector, 0);
-            svm_inject_extint(v, intr_vector, VMX_DELIVER_NO_ERROR_CODE);
-            hvm_interrupt_post(v, intr_vector, intr_type);
+            svm_inject_extint(v, intr_vector);
             break;
         case APIC_DM_SMI:
         case APIC_DM_NMI:
@@ -158,6 +165,7 @@ asmlinkage void svm_intr_assist(void) 
             BUG();
             break;
         }
+        hvm_interrupt_post(v, intr_vector, intr_type);
     }
 }
 
--- xen/arch/x86/hvm/svm/svm.c.orig	2006-10-25 13:00:04.000000000 -0400
+++ xen/arch/x86/hvm/svm/svm.c	2006-10-25 14:17:09.000000000 -0400
@@ -196,6 +196,7 @@ static inline void svm_inject_exception(
     ASSERT(vmcb->eventinj.fields.v == 0);
     
     vmcb->eventinj = event;
+    v->arch.hvm_svm.inject_event=1;
 }
 
 static void stop_svm(void)
@@ -2590,6 +2591,7 @@ asmlinkage void svm_vmexit_handler(struc
 
     vmcb->tlb_control = 1;
 
+    v->arch.hvm_svm.inject_event = 0;
 
     if (exit_reason == VMEXIT_INVALID)
     {
@@ -2802,6 +2804,11 @@ asmlinkage void svm_vmexit_handler(struc
         svm_inject_exception(v, TRAP_double_fault, 1, 0);
         break;
 
+    case VMEXIT_VINTR:
+	vmcb->vintr.fields.irq = 0;
+	vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_VINTR;
+        break;
+
     case VMEXIT_INTR:
         break;
 
--- xen/include/asm-x86/hvm/svm/vmcb.h.orig	2006-10-25 14:17:39.000000000 -0400
+++ xen/include/asm-x86/hvm/svm/vmcb.h	2006-10-25 14:18:30.000000000 -0400
@@ -484,6 +484,7 @@ struct arch_svm_struct {
     u32                 *msrpm;
     u64                 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */
     int                 saved_irq_vector;
+    u32                 inject_event;
     u32                 launch_core;
     u32                 asid_core;
     

openSUSE Build Service is sponsored by