WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 1/2] x86, hvm: allow another vcpu to receive PIT IRQ

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 1/2] x86, hvm: allow another vcpu to receive PIT IRQ (support kexec/kdump on hvm)
From: Kouya Shimura <kouya@xxxxxxxxxxxxxx>
Date: Tue, 30 Jun 2009 15:57:05 +0900
Cc: Keir Fraser <keir.fraser@xxxxxxxxxxxxx>
Delivery-date: Tue, 30 Jun 2009 00:02:24 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <7kr5x2nrcd.fsf@xxxxxxxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <7kr5x2nrcd.fsf@xxxxxxxxxxxxxxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
This patch is needed for kexec/kdump on hvm since kdump halts bsp.

- allow another vcpu than bsp to receive PIT IRQ
- deliver PIT IRQ to the vcpu whose LINT0 is ExtINT mode

Signed-off-by: Kouya Shimura <kouya@xxxxxxxxxxxxxx>

diff -r 7397608bce87 xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c  Mon Jun 29 15:50:32 2009 +0100
+++ b/xen/arch/x86/hvm/i8254.c  Tue Jun 30 13:15:31 2009 +0900
@@ -42,7 +42,7 @@
 #define vcpu_vpit(vcpu)  (domain_vpit((vcpu)->domain))
 #define vpit_domain(pit) (container_of((pit), struct domain, \
                                        arch.hvm_domain.pl_time.vpit))
-#define vpit_vcpu(pit)   (vpit_domain(pit)->vcpu[0])
+#define vpit_vcpu(pit)   (pit->pt0.vcpu)
 
 #define RW_STATE_LSB 1
 #define RW_STATE_MSB 2
@@ -174,14 +174,11 @@ static void pit_load_count(PITState *pit
     if ( val == 0 )
         val = 0x10000;
 
-    if ( v == NULL )
-        pit->count_load_time[channel] = 0;
-    else
-        pit->count_load_time[channel] = get_guest_time(v);
+    pit->count_load_time[channel] = get_guest_time(v);
     s->count = val;
     period = DIV_ROUND(val * SYSTEM_TIME_HZ, PIT_FREQ);
 
-    if ( (v == NULL) || !is_hvm_vcpu(v) || (channel != 0) )
+    if ( !is_hvm_vcpu(v) || (channel != 0) )
         return;
 
     switch ( s->mode )
@@ -397,6 +394,15 @@ static int pit_save(struct domain *d, hv
     return rc;
 }
 
+static struct vcpu *find_pic_intr_accept_vcpu(struct domain *d)
+{
+    struct vcpu *v;
+    for_each_vcpu(d, v)
+        if ( vlapic_accept_pic_intr(v) )
+            return v;
+    return d->vcpu[0];
+}
+
 static int pit_load(struct domain *d, hvm_domain_context_t *h)
 {
     PITState *pit = domain_vpit(d);
@@ -415,7 +421,8 @@ static int pit_load(struct domain *d, hv
      * time jitter here, but the wall-clock will have jumped massively, so 
      * we hope the guest can handle it.
      */
-    pit->pt0.last_plt_gtime = get_guest_time(d->vcpu[0]);
+    pit->pt0.vcpu = find_pic_intr_accept_vcpu(d);
+    pit->pt0.last_plt_gtime = get_guest_time(pit->pt0.vcpu);
     for ( i = 0; i < 3; i++ )
         pit_load_count(pit, i, pit->hw.channels[i].count);
 
@@ -432,7 +439,9 @@ void pit_reset(struct domain *d)
     struct hvm_hw_pit_channel *s;
     int i;
 
-    destroy_periodic_time(&pit->pt0);
+    if ( is_hvm_domain(d) )
+        destroy_periodic_time(&pit->pt0);
+
     pit->pt0.source = PTSRC_isa;
 
     spin_lock(&pit->lock);
@@ -452,14 +461,43 @@ void pit_init(struct vcpu *v, unsigned l
 {
     PITState *pit = vcpu_vpit(v);
 
+    ASSERT(v->vcpu_id == 0);
+
     spin_lock_init(&pit->lock);
 
     register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io);
     register_portio_handler(v->domain, 0x61, 1, handle_speaker_io);
 
+    pit->pt0.vcpu = v; /* VCPU0 */
+
     pit_reset(v->domain);
 }
 
+void pit_bind_vcpu(struct vcpu *v)
+{
+    PITState *pit = vcpu_vpit(v);
+    struct periodic_time *pt = &pit->pt0;
+
+    ASSERT(is_hvm_vcpu(v));
+
+    spin_lock(&pit->lock);
+    if ( pt->vcpu != v )
+    {
+        /*
+         * Recreate the platform timer only if it was previously created
+         * as a periodic timer.
+         * For one-shot timer, the timer works along with the previous
+         * vcpu but kicks the new vcpu.
+         */
+        pt->vcpu = v;
+        if ( pt->cb != NULL && !pt->one_shot )
+            /* XXX: delta should be recalculated ? */
+            create_periodic_time(v, pt, pt->period_cycles, pt->period_cycles,
+                                 pt->irq, pt->cb, pt->priv);
+    }
+    spin_unlock(&pit->lock);
+}
+
 void pit_deinit(struct domain *d)
 {
     PITState *pit = domain_vpit(d);
diff -r 7397608bce87 xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Mon Jun 29 15:50:32 2009 +0100
+++ b/xen/arch/x86/hvm/irq.c    Tue Jun 30 13:15:31 2009 +0900
@@ -348,7 +348,6 @@ struct hvm_intack hvm_vcpu_ack_pending_i
             intack = hvm_intack_none;
         break;
     case hvm_intsrc_pic:
-        ASSERT(v->vcpu_id == 0);
         if ( (vector = vpic_ack_pending_irq(v)) == -1 )
             intack = hvm_intack_none;
         else
diff -r 7397608bce87 xen/arch/x86/hvm/vlapic.c
--- a/xen/arch/x86/hvm/vlapic.c Mon Jun 29 15:50:32 2009 +0100
+++ b/xen/arch/x86/hvm/vlapic.c Tue Jun 30 13:15:31 2009 +0900
@@ -697,6 +697,9 @@ static int vlapic_write(struct vcpu *v, 
             val |= APIC_LVT_MASKED;
         val &= vlapic_lvt_mask[(offset - APIC_LVTT) >> 4];
         vlapic_set_reg(vlapic, offset, val);
+        if ( offset == APIC_LVT0 &&
+             (val & (APIC_MODE_MASK|APIC_LVT_MASKED)) == APIC_DM_EXTINT )
+            pit_bind_vcpu(vlapic_vcpu(vlapic));
         break;
 
     case APIC_TMICT:
@@ -782,12 +785,11 @@ int vlapic_accept_pic_intr(struct vcpu *
     uint32_t lvt0 = vlapic_get_reg(vlapic, APIC_LVT0);
 
     /*
-     * Only CPU0 is wired to the 8259A. INTA cycles occur if LINT0 is set up
-     * accept ExtInts, or if the LAPIC is disabled (so LINT0 behaves as INTR).
+     * INTA cycles occur if LINT0 is set up accept ExtInts,
+     * or if the LAPIC is disabled (so LINT0 behaves as INTR).
      */
-    return ((v->vcpu_id == 0) &&
-            (((lvt0 & (APIC_MODE_MASK|APIC_LVT_MASKED)) == APIC_DM_EXTINT) ||
-             vlapic_hw_disabled(vlapic)));
+    return (((lvt0 & (APIC_MODE_MASK|APIC_LVT_MASKED)) == APIC_DM_EXTINT) ||
+             vlapic_hw_disabled(vlapic));
 }
 
 int vlapic_has_pending_irq(struct vcpu *v)
diff -r 7397608bce87 xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h     Mon Jun 29 15:50:32 2009 +0100
+++ b/xen/include/asm-x86/hvm/vpt.h     Tue Jun 30 13:15:31 2009 +0900
@@ -162,7 +162,7 @@ void destroy_periodic_time(struct period
 
 int pv_pit_handler(int port, int data, int write);
 void pit_reset(struct domain *d);
-
+void pit_bind_vcpu(struct vcpu *v);
 void pit_init(struct vcpu *v, unsigned long cpu_khz);
 void pit_stop_channel0_irq(PITState * pit);
 void pit_deinit(struct domain *d);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel