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
|