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] Xen: enhanced PV on HVM

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH] Xen: enhanced PV on HVM
From: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Date: Tue, 9 Mar 2010 16:05:23 +0000
Delivery-date: Tue, 09 Mar 2010 08:06:21 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
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>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Alpine 2.00 (DEB 1167 2008-08-23)
Hi all,
this patch is for Xen and it is derived from an earlier patch by Shen.
The changes introduced by this patch include:

- add support to some vcpuops and physdevops for HVM domains;

- introduce a new interrupt callback method for HVM domains;

- allow HVM guests to map emulated interrupts to pirqs;

in addition to these modifications, the new version of the patch
supports remapping of real hardware interrupts into evtchns.

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
Signed-off-by: Sheng Yang <sheng@xxxxxxxxxxxxxxx>

---

diff -r 3bb163b74673 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/arch/x86/domain.c     Tue Mar 09 15:34:11 2010 +0000
@@ -496,6 +496,16 @@
             if ( !IO_APIC_IRQ(i) )
                 d->arch.irq_pirq[i] = d->arch.pirq_irq[i] = i;
 
+        d->arch.pirq_emuirq = xmalloc_array(int, d->nr_pirqs);
+        d->arch.emuirq_pirq = xmalloc_array(int, d->nr_pirqs);
+        if ( !d->arch.pirq_emuirq || !d->arch.emuirq_pirq )
+            goto fail;
+        memset(d->arch.pirq_emuirq, -1,
+               d->nr_pirqs * sizeof(*d->arch.pirq_emuirq));
+        memset(d->arch.emuirq_pirq, -1,
+               d->nr_pirqs * sizeof(*d->arch.emuirq_pirq));
+
+
         if ( (rc = iommu_domain_init(d)) != 0 )
             goto fail;
 
@@ -686,7 +696,16 @@
 
     if ( is_hvm_vcpu(v) )
     {
+        unsigned long eip, cs;
         hvm_set_info_guest(v);
+
+        eip = c(user_regs.eip);
+        if (eip != 0) {
+            cs = eip >> 12 << 8;
+            hvm_vcpu_reset_state(v, cs, 0);
+            hvm_funcs.set_tsc_offset(v, 0);
+        }
+
         goto out;
     }
 
diff -r 3bb163b74673 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/arch/x86/hvm/hvm.c    Tue Mar 09 15:34:11 2010 +0000
@@ -2231,6 +2231,21 @@
     return rc;
 }
 
+static long hvm_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
+{
+    switch ( cmd )
+    {
+        case PHYSDEVOP_setup_gsi:
+        case PHYSDEVOP_map_pirq:
+        case PHYSDEVOP_unmap_pirq:
+        case PHYSDEVOP_eoi:
+        case PHYSDEVOP_irq_status_query:
+            return do_physdev_op(cmd, arg);
+        default:
+            return -ENOSYS;
+    }
+}
+
 static long hvm_vcpu_op(
     int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg)
 {
@@ -2240,6 +2255,14 @@
     {
     case VCPUOP_register_runstate_memory_area:
     case VCPUOP_get_runstate_info:
+    case VCPUOP_initialise:
+    case VCPUOP_up:
+    case VCPUOP_is_up:
+    case VCPUOP_set_periodic_timer:
+    case VCPUOP_stop_periodic_timer:
+    case VCPUOP_set_singleshot_timer:
+    case VCPUOP_stop_singleshot_timer:
+    case VCPUOP_register_vcpu_time_memory_area:
         rc = do_vcpu_op(cmd, vcpuid, arg);
         break;
     default:
@@ -2262,9 +2285,11 @@
     [ __HYPERVISOR_memory_op ] = (hvm_hypercall_t *)hvm_memory_op,
     [ __HYPERVISOR_grant_table_op ] = (hvm_hypercall_t *)hvm_grant_table_op,
     [ __HYPERVISOR_vcpu_op ] = (hvm_hypercall_t *)hvm_vcpu_op,
+    [ __HYPERVISOR_physdev_op ] = (hvm_hypercall_t *)hvm_physdev_op,
     HYPERCALL(xen_version),
     HYPERCALL(event_channel_op),
     HYPERCALL(sched_op),
+    HYPERCALL(set_timer_op),
     HYPERCALL(hvm_op)
 };
 
@@ -2296,6 +2321,14 @@
     {
     case VCPUOP_register_runstate_memory_area:
     case VCPUOP_get_runstate_info:
+    case VCPUOP_initialise:
+    case VCPUOP_up:
+    case VCPUOP_is_up:
+    case VCPUOP_set_periodic_timer:
+    case VCPUOP_stop_periodic_timer:
+    case VCPUOP_set_singleshot_timer:
+    case VCPUOP_stop_singleshot_timer:
+    case VCPUOP_register_vcpu_time_memory_area:
         rc = compat_vcpu_op(cmd, vcpuid, arg);
         break;
     default:
@@ -2306,13 +2339,33 @@
     return rc;
 }
 
+static long hvm_physdev_op_compat32(
+    int cmd, XEN_GUEST_HANDLE(void) arg)
+{
+    switch ( cmd )
+    {
+        case PHYSDEVOP_setup_gsi:
+        case PHYSDEVOP_map_pirq:
+        case PHYSDEVOP_unmap_pirq:
+        case PHYSDEVOP_eoi:
+        case PHYSDEVOP_irq_status_query:
+            return compat_physdev_op(cmd, arg);
+        break;
+    default:
+            return -ENOSYS;
+        break;
+    }
+}
+
 static hvm_hypercall_t *hvm_hypercall64_table[NR_hypercalls] = {
     [ __HYPERVISOR_memory_op ] = (hvm_hypercall_t *)hvm_memory_op,
     [ __HYPERVISOR_grant_table_op ] = (hvm_hypercall_t *)hvm_grant_table_op,
     [ __HYPERVISOR_vcpu_op ] = (hvm_hypercall_t *)hvm_vcpu_op,
+    [ __HYPERVISOR_physdev_op ] = (hvm_hypercall_t *)hvm_physdev_op,
     HYPERCALL(xen_version),
     HYPERCALL(event_channel_op),
     HYPERCALL(sched_op),
+    HYPERCALL(set_timer_op),
     HYPERCALL(hvm_op)
 };
 
@@ -2320,9 +2373,11 @@
     [ __HYPERVISOR_memory_op ] = (hvm_hypercall_t *)hvm_memory_op_compat32,
     [ __HYPERVISOR_grant_table_op ] = (hvm_hypercall_t 
*)hvm_grant_table_op_compat32,
     [ __HYPERVISOR_vcpu_op ] = (hvm_hypercall_t *)hvm_vcpu_op_compat32,
+    [ __HYPERVISOR_physdev_op ] = (hvm_hypercall_t *)hvm_physdev_op_compat32,
     HYPERCALL(xen_version),
     HYPERCALL(event_channel_op),
     HYPERCALL(sched_op),
+    HYPERCALL(set_timer_op),
     HYPERCALL(hvm_op)
 };
 
diff -r 3bb163b74673 xen/arch/x86/hvm/irq.c
--- a/xen/arch/x86/hvm/irq.c    Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/arch/x86/hvm/irq.c    Tue Mar 09 15:34:11 2010 +0000
@@ -23,8 +23,29 @@
 #include <xen/types.h>
 #include <xen/event.h>
 #include <xen/sched.h>
+#include <xen/irq.h>
 #include <asm/hvm/domain.h>
 #include <asm/hvm/support.h>
+
+/* Must be called with hvm_domain->irq_lock hold */
+static void assert_irq(struct domain *d, unsigned ioapic_gsi, unsigned pic_irq)
+{
+    int pirq = domain_emuirq_to_pirq(d, ioapic_gsi);
+    if ( pirq >= 0 )
+    {
+        send_guest_pirq(d, pirq);
+        return;
+    }
+    vioapic_irq_positive_edge(d, ioapic_gsi);
+    vpic_irq_positive_edge(d, pic_irq);
+}
+
+/* Must be called with hvm_domain->irq_lock hold */
+static void deassert_irq(struct domain *d, unsigned isa_irq)
+{
+    if ( domain_emuirq_to_pirq(d, isa_irq) <= 0 )
+        vpic_irq_negative_edge(d, isa_irq);
+}
 
 static void __hvm_pci_intx_assert(
     struct domain *d, unsigned int device, unsigned int intx)
@@ -45,10 +66,7 @@
     isa_irq = hvm_irq->pci_link.route[link];
     if ( (hvm_irq->pci_link_assert_count[link]++ == 0) && isa_irq &&
          (hvm_irq->gsi_assert_count[isa_irq]++ == 0) )
-    {
-        vioapic_irq_positive_edge(d, isa_irq);
-        vpic_irq_positive_edge(d, isa_irq);
-    }
+        assert_irq(d, isa_irq, isa_irq);
 }
 
 void hvm_pci_intx_assert(
@@ -77,7 +95,7 @@
     isa_irq = hvm_irq->pci_link.route[link];
     if ( (--hvm_irq->pci_link_assert_count[link] == 0) && isa_irq &&
          (--hvm_irq->gsi_assert_count[isa_irq] == 0) )
-        vpic_irq_negative_edge(d, isa_irq);
+        deassert_irq(d, isa_irq);
 }
 
 void hvm_pci_intx_deassert(
@@ -100,10 +118,7 @@
 
     if ( !__test_and_set_bit(isa_irq, &hvm_irq->isa_irq.i) &&
          (hvm_irq->gsi_assert_count[gsi]++ == 0) )
-    {
-        vioapic_irq_positive_edge(d, gsi);
-        vpic_irq_positive_edge(d, isa_irq);
-    }
+        assert_irq(d, gsi, isa_irq);
 
     spin_unlock(&d->arch.hvm_domain.irq_lock);
 }
@@ -120,7 +135,7 @@
 
     if ( __test_and_clear_bit(isa_irq, &hvm_irq->isa_irq.i) &&
          (--hvm_irq->gsi_assert_count[gsi] == 0) )
-        vpic_irq_negative_edge(d, isa_irq);
+        deassert_irq(d, isa_irq);
 
     spin_unlock(&d->arch.hvm_domain.irq_lock);
 }
@@ -185,16 +200,16 @@
 
 void hvm_assert_evtchn_irq(struct vcpu *v)
 {
-    if ( v->vcpu_id != 0 )
-        return;
-
     if ( unlikely(in_irq() || !local_irq_is_enabled()) )
     {
         tasklet_schedule(&v->arch.hvm_vcpu.assert_evtchn_irq_tasklet);
         return;
     }
 
-    hvm_set_callback_irq_level(v);
+    if (is_hvm_pv_evtchn_vcpu(v))
+        vcpu_kick(v);
+    else
+        hvm_set_callback_irq_level(v);
 }
 
 void hvm_set_pci_link_route(struct domain *d, u8 link, u8 isa_irq)
@@ -251,7 +266,7 @@
 
     via_type = (uint8_t)(via >> 56) + 1;
     if ( ((via_type == HVMIRQ_callback_gsi) && (via == 0)) ||
-         (via_type > HVMIRQ_callback_pci_intx) )
+         (via_type > HVMIRQ_callback_vector) )
         via_type = HVMIRQ_callback_none;
 
     spin_lock(&d->arch.hvm_domain.irq_lock);
@@ -297,6 +312,9 @@
         if ( hvm_irq->callback_via_asserted )
              __hvm_pci_intx_assert(d, pdev, pintx);
         break;
+    case HVMIRQ_callback_vector:
+        hvm_irq->callback_via.vector = (uint8_t)via;
+        break;
     default:
         break;
     }
@@ -312,6 +330,10 @@
     case HVMIRQ_callback_pci_intx:
         printk("PCI INTx Dev 0x%02x Int%c\n", pdev, 'A' + pintx);
         break;
+    case HVMIRQ_callback_vector:
+        printk("Set HVMIRQ_callback_vector to %u\n",
+               hvm_irq->callback_via.vector);
+        break;
     default:
         printk("None\n");
         break;
@@ -323,6 +345,10 @@
     struct hvm_domain *plat = &v->domain->arch.hvm_domain;
     int vector;
 
+    if (plat->irq.callback_via_type == HVMIRQ_callback_vector &&
+            vcpu_info(v, evtchn_upcall_pending))
+        return hvm_intack_vector(plat->irq.callback_via.vector);
+ 
     if ( unlikely(v->nmi_pending) )
         return hvm_intack_nmi;
 
@@ -363,6 +389,8 @@
     case hvm_intsrc_lapic:
         if ( !vlapic_ack_pending_irq(v, intack.vector) )
             intack = hvm_intack_none;
+        break;
+    case hvm_intsrc_vector:
         break;
     default:
         intack = hvm_intack_none;
diff -r 3bb163b74673 xen/arch/x86/hvm/vmx/intr.c
--- a/xen/arch/x86/hvm/vmx/intr.c       Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/arch/x86/hvm/vmx/intr.c       Tue Mar 09 15:34:11 2010 +0000
@@ -164,7 +164,8 @@
     {
         HVMTRACE_2D(INJ_VIRQ, intack.vector, /*fake=*/ 0);
         vmx_inject_extint(intack.vector);
-        pt_intr_post(v, intack);
+        if (intack.source != hvm_intsrc_vector)
+             pt_intr_post(v, intack);
     }
 
     /* Is there another IRQ to queue up behind this one? */
diff -r 3bb163b74673 xen/arch/x86/irq.c
--- a/xen/arch/x86/irq.c        Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/arch/x86/irq.c        Tue Mar 09 15:34:11 2010 +0000
@@ -1394,7 +1394,10 @@
     {
         for ( i = 16; i < nr_irqs_gsi; i++ )
             if ( !d->arch.pirq_irq[i] )
-                break;
+            {
+                if ( !is_hvm_domain(d) || d->arch.pirq_emuirq[i] < 0 )
+                    break;
+            }
         if ( i == nr_irqs_gsi )
             return -ENOSPC;
     }
@@ -1402,7 +1405,10 @@
     {
         for ( i = d->nr_pirqs - 1; i >= nr_irqs_gsi; i-- )
             if ( !d->arch.pirq_irq[i] )
-                break;
+            {
+                if ( !is_hvm_domain(d) || d->arch.pirq_emuirq[i] < 0 )
+                    break;
+            }
         if ( i < nr_irqs_gsi )
             return -ENOSPC;
     }
@@ -1733,3 +1739,65 @@
         peoi[sp].ready = 1;
     flush_ready_eoi();
 }
+
+int map_domain_emuirq_pirq(
+    struct domain *d, int pirq, int emuirq, int type, void *data)
+{
+    int old_emuirq, old_pirq, ret = 0;
+
+    ASSERT(spin_is_locked(&d->event_lock));
+
+    if ( !is_hvm_domain(d) )
+        return -EINVAL;
+
+    if ( pirq < 0 || pirq >= d->nr_pirqs || emuirq < 0 || emuirq >= nr_irqs )
+    {
+        dprintk(XENLOG_G_ERR, "dom%d: invalid pirq %d or irq %d\n",
+                d->domain_id, pirq, emuirq);
+        return -EINVAL;
+    }
+
+    old_emuirq = domain_pirq_to_emuirq(d, pirq);
+    old_pirq = domain_emuirq_to_pirq(d, emuirq);
+
+    if ( (old_emuirq > 0 && (old_emuirq != emuirq) ) ||
+         (old_pirq > 0 && (old_pirq != pirq)) )
+    {
+        dprintk(XENLOG_G_WARNING, "dom%d: pirq %d or emuirq %d already 
mapped\n",
+                d->domain_id, pirq, emuirq);
+        return 0;
+    }
+
+    d->arch.pirq_emuirq[pirq] = emuirq;
+    d->arch.emuirq_pirq[emuirq] = pirq;
+
+    return ret;
+}
+
+int unmap_domain_pirq_emuirq(struct domain *d, int pirq)
+{
+    int emuirq, ret = 0;
+
+    if ( !is_hvm_domain(d) )
+        return -EINVAL;
+
+    if ( (pirq < 0) || (pirq >= d->nr_pirqs) )
+        return -EINVAL;
+
+    ASSERT(spin_is_locked(&d->event_lock));
+
+    emuirq = domain_pirq_to_emuirq(d, pirq);
+    if ( emuirq <= 0 )
+    {
+        dprintk(XENLOG_G_ERR, "dom%d: pirq %d not mapped\n",
+                d->domain_id, pirq);
+        ret = -EINVAL;
+        goto done;
+    }
+
+    d->arch.pirq_emuirq[pirq] = -1;
+    d->arch.emuirq_pirq[emuirq] = -1;
+
+ done:
+    return ret;
+}
diff -r 3bb163b74673 xen/arch/x86/physdev.c
--- a/xen/arch/x86/physdev.c    Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/arch/x86/physdev.c    Tue Mar 09 15:34:11 2010 +0000
@@ -44,6 +44,49 @@
 
     if ( d == NULL )
         return -ESRCH;
+   
+    if ( map->domid == DOMID_SELF && is_hvm_domain(d) )
+    {
+        spin_lock(&d->event_lock);
+        switch ( map->type )
+        {
+            case MAP_PIRQ_TYPE_GSI :
+                {
+                    struct hvm_irq_dpci *hvm_irq_dpci;
+                    struct hvm_girq_dpci_mapping *girq;
+                    uint32_t machine_gsi = map->pirq;
+
+                    hvm_irq_dpci = domain_get_irq_dpci(d);
+                    if (hvm_irq_dpci) {
+                        list_for_each_entry ( girq, 
&hvm_irq_dpci->girq[map->index], list ) {
+                            machine_gsi = girq->machine_gsi;
+                        }
+                    }
+                    if ( machine_gsi != map->pirq )
+                    {
+                        map->index = domain_pirq_to_irq(d, machine_gsi);
+                        pirq = machine_gsi;
+                    }
+                    else
+                    {
+                        pirq = map->pirq;
+                        if ( pirq < 0 )
+                        {
+                            pirq = get_free_pirq(d, map->type, map->index);
+                        }
+                    }
+                    ret = map_domain_emuirq_pirq(d, pirq, map->index, 
map->type, NULL);
+                    map->pirq = pirq;
+                }
+                break;
+            default :
+                ret = -EINVAL;
+                dprintk(XENLOG_G_WARNING, "map type %d not supported yet\n", 
map->type);
+                break;
+        }
+        spin_unlock(&d->event_lock);
+        return ret;
+    }
 
     if ( !IS_PRIV_FOR(current->domain, d) )
     {
@@ -143,7 +186,18 @@
             goto done;
         }
         else
-            pirq = map->pirq;
+        {
+            if ( is_hvm_domain(d) && domain_pirq_to_emuirq(d, map->pirq) >= 0)
+                pirq = get_free_pirq(d, map->type, map->index);
+            else
+                pirq = map->pirq;
+            if ( pirq < 0 )
+            {
+                dprintk(XENLOG_G_ERR, "dom%d: no free pirq\n", d->domain_id);
+                ret = pirq;
+                goto done;
+            }
+        }
     }
 
     ret = map_domain_pirq(d, pirq, irq, map->type, map_data);
@@ -172,6 +226,14 @@
 
     if ( d == NULL )
         return -ESRCH;
+
+    if ( is_hvm_domain(d) )
+    {
+        spin_lock(&d->event_lock);
+        ret = unmap_domain_pirq_emuirq(d, unmap->pirq);
+        spin_unlock(&d->event_lock);
+        goto free_domain;
+    }
 
     ret = -EPERM;
     if ( !IS_PRIV_FOR(current->domain, d) )
@@ -206,7 +268,10 @@
             break;
         if ( v->domain->arch.pirq_eoi_map )
             evtchn_unmask(v->domain->pirq_to_evtchn[eoi.irq]);
-        ret = pirq_guest_eoi(v->domain, eoi.irq);
+        if ( !is_hvm_domain(v->domain) )
+            ret = pirq_guest_eoi(v->domain, eoi.irq);
+        else
+            ret = 0;
         break;
     }
 
@@ -261,6 +326,12 @@
         if ( (irq < 0) || (irq >= v->domain->nr_pirqs) )
             break;
         irq_status_query.flags = 0;
+        if ( is_hvm_domain(v->domain) )
+        {
+            ret = copy_to_guest(arg, &irq_status_query, 1) ? -EFAULT : 0;
+            break;
+        }
+
         /*
          * Even edge-triggered or message-based IRQs can need masking from
          * time to time. If teh guest is not dynamically checking for this
@@ -465,6 +536,11 @@
     case PHYSDEVOP_setup_gsi: {
         struct physdev_setup_gsi setup_gsi;
 
+        /* In the HVM case we are setting up an emulated GSI, therefore
+         * there is no need to do anything here */
+        if ( is_hvm_domain(v->domain) )
+            return 0;
+
         ret = -EPERM;
         if ( !IS_PRIV(v->domain) )
             break;
diff -r 3bb163b74673 xen/common/event_channel.c
--- a/xen/common/event_channel.c        Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/common/event_channel.c        Tue Mar 09 15:34:11 2010 +0000
@@ -305,7 +305,7 @@
     if ( (pirq < 0) || (pirq >= d->nr_pirqs) )
         return -EINVAL;
 
-    if ( !irq_access_permitted(d, pirq) )
+    if ( !is_hvm_domain(d) && !irq_access_permitted(d, pirq) )
         return -EPERM;
 
     spin_lock(&d->event_lock);
@@ -319,12 +319,15 @@
     chn = evtchn_from_port(d, port);
 
     d->pirq_to_evtchn[pirq] = port;
-    rc = pirq_guest_bind(d->vcpu[0], pirq, 
-                         !!(bind->flags & BIND_PIRQ__WILL_SHARE));
-    if ( rc != 0 )
+    if ( !is_hvm_domain(d) )
     {
-        d->pirq_to_evtchn[pirq] = 0;
-        goto out;
+        rc = pirq_guest_bind(d->vcpu[0], pirq, 
+                !!(bind->flags & BIND_PIRQ__WILL_SHARE));
+        if ( rc != 0 )
+        {
+            d->pirq_to_evtchn[pirq] = 0;
+            goto out;
+        }
     }
 
     chn->state  = ECS_PIRQ;
@@ -376,7 +379,8 @@
         break;
 
     case ECS_PIRQ:
-        pirq_guest_unbind(d1, chn1->u.pirq);
+        if ( !is_hvm_domain(d1) )
+            pirq_guest_unbind(d1, chn1->u.pirq);
         d1->pirq_to_evtchn[chn1->u.pirq] = 0;
         break;
 
@@ -636,8 +640,17 @@
     /*
      * It should not be possible to race with __evtchn_close():
      * The caller of this function must synchronise with pirq_guest_unbind().
+     *
+     * In the HVM case port is 0 when the guest disable the
+     * emulated interrupt\evtchn.
      */
-    ASSERT(port != 0);
+    if (!port)
+    {
+        if ( is_hvm_domain(d) )
+            return 0;
+        else
+            return -EINVAL;
+    }
 
     chn = evtchn_from_port(d, port);
     return evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port);
@@ -824,6 +837,7 @@
 long do_event_channel_op(int cmd, XEN_GUEST_HANDLE(void) arg)
 {
     long rc;
+    struct domain *d = current->domain;
 
     switch ( cmd )
     {
@@ -852,6 +866,10 @@
         if ( copy_from_guest(&bind_virq, arg, 1) != 0 )
             return -EFAULT;
         rc = evtchn_bind_virq(&bind_virq);
+        if ( is_hvm_domain(d) && bind_virq.virq == VIRQ_TIMER) {
+            update_domain_wallclock_time(d);
+            hvm_funcs.set_tsc_offset(d->vcpu[0], 0);
+        }
         if ( (rc == 0) && (copy_to_guest(arg, &bind_virq, 1) != 0) )
             rc = -EFAULT; /* Cleaning up here would be a mess! */
         break;
diff -r 3bb163b74673 xen/drivers/passthrough/io.c
--- a/xen/drivers/passthrough/io.c      Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/drivers/passthrough/io.c      Tue Mar 09 15:34:11 2010 +0000
@@ -446,7 +446,11 @@
 extern int vmsi_deliver(struct domain *d, int pirq);
 static int hvm_pci_msi_assert(struct domain *d, int pirq)
 {
-    return vmsi_deliver(d, pirq);
+    int emuirq = domain_pirq_to_emuirq(d, pirq);
+    if ( emuirq < 0 )
+        return vmsi_deliver(d, pirq);
+    else
+        return send_guest_pirq(d, pirq);
 }
 #endif
 
@@ -480,7 +484,10 @@
         {
             device = digl->device;
             intx = digl->intx;
-            hvm_pci_intx_assert(d, device, intx);
+            if ( is_hvm_domain(d) && domain_pirq_to_emuirq(d, pirq) >=0 )
+                send_guest_pirq(d, pirq);
+            else
+                hvm_pci_intx_assert(d, device, intx);
             hvm_irq_dpci->mirq[pirq].pending++;
 
 #ifdef SUPPORT_MSI_REMAPPING
diff -r 3bb163b74673 xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/include/asm-x86/domain.h      Tue Mar 09 15:34:11 2010 +0000
@@ -278,6 +278,9 @@
     /* NB. protected by d->event_lock and by irq_desc[irq].lock */
     int *irq_pirq;
     int *pirq_irq;
+    /* pirq to emulated irq and vice versa */
+    int *emuirq_pirq;
+    int *pirq_emuirq;
 
     /* Shared page for notifying that explicit PIRQ EOI is required. */
     unsigned long *pirq_eoi_map;
diff -r 3bb163b74673 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/include/asm-x86/hvm/hvm.h     Tue Mar 09 15:34:11 2010 +0000
@@ -33,7 +33,8 @@
     hvm_intsrc_pic,
     hvm_intsrc_lapic,
     hvm_intsrc_nmi,
-    hvm_intsrc_mce
+    hvm_intsrc_mce,
+    hvm_intsrc_vector
 };
 struct hvm_intack {
     uint8_t source; /* enum hvm_intsrc */
@@ -44,6 +45,7 @@
 #define hvm_intack_lapic(vec) ( (struct hvm_intack) { hvm_intsrc_lapic, vec } )
 #define hvm_intack_nmi        ( (struct hvm_intack) { hvm_intsrc_nmi,   2 } )
 #define hvm_intack_mce        ( (struct hvm_intack) { hvm_intsrc_mce,   18 } )
+#define hvm_intack_vector(vec)( (struct hvm_intack) { hvm_intsrc_vector, vec } 
)
 enum hvm_intblk {
     hvm_intblk_none,      /* not blocked (deliverable) */
     hvm_intblk_shadow,    /* MOV-SS or STI shadow */
diff -r 3bb163b74673 xen/include/asm-x86/hvm/irq.h
--- a/xen/include/asm-x86/hvm/irq.h     Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/include/asm-x86/hvm/irq.h     Tue Mar 09 15:34:11 2010 +0000
@@ -54,12 +54,14 @@
         enum {
             HVMIRQ_callback_none,
             HVMIRQ_callback_gsi,
-            HVMIRQ_callback_pci_intx
+            HVMIRQ_callback_pci_intx,
+            HVMIRQ_callback_vector
         } callback_via_type;
     };
     union {
         uint32_t gsi;
         struct { uint8_t dev, intx; } pci;
+        uint32_t vector;
     } callback_via;
 
     /* Number of INTx wires asserting each PCI-ISA link. */
diff -r 3bb163b74673 xen/include/asm-x86/irq.h
--- a/xen/include/asm-x86/irq.h Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/include/asm-x86/irq.h Tue Mar 09 15:34:11 2010 +0000
@@ -112,6 +112,9 @@
 int map_domain_pirq(struct domain *d, int pirq, int irq, int type,
                            void *data);
 int unmap_domain_pirq(struct domain *d, int pirq);
+int map_domain_emuirq_pirq(struct domain *d, int pirq, int irq, int type,
+                           void *data);
+int unmap_domain_pirq_emuirq(struct domain *d, int pirq);
 int get_free_pirq(struct domain *d, int type, int index);
 void free_domain_pirqs(struct domain *d);
 
@@ -147,5 +150,7 @@
 
 #define domain_pirq_to_irq(d, pirq) ((d)->arch.pirq_irq[pirq])
 #define domain_irq_to_pirq(d, irq) ((d)->arch.irq_pirq[irq])
+#define domain_pirq_to_emuirq(d, pirq) ((d)->arch.pirq_emuirq[pirq])
+#define domain_emuirq_to_pirq(d, emuirq) ((d)->arch.emuirq_pirq[emuirq])
 
 #endif /* _ASM_HW_IRQ_H */
diff -r 3bb163b74673 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Fri Feb 12 09:24:18 2010 +0000
+++ b/xen/include/xen/sched.h   Tue Mar 09 15:34:11 2010 +0000
@@ -592,6 +592,9 @@
 #define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist))
 
 #define is_hvm_domain(d) ((d)->is_hvm)
+#define is_hvm_pv_evtchn_domain(d) (is_hvm_domain(d) && \
+           d->arch.hvm_domain.irq.callback_via_type == HVMIRQ_callback_vector)
+#define is_hvm_pv_evtchn_vcpu(v) (is_hvm_pv_evtchn_domain(v->domain))
 #define is_hvm_vcpu(v)   (is_hvm_domain(v->domain))
 #define need_iommu(d)    ((d)->need_iommu)
 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

<Prev in Thread] Current Thread [Next in Thread>