# HG changeset patch
# User Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
# Date 1228459388 -32400
# Node ID f0a9a58608a08288f554a18758a19e97a51879f2
# Parent c15577ad46f21c6db393ebc516ab5ddd36341c58
IA64: implement PHYSDEVOP_pirq_eoi_gmfn and related stuff.
This patch is ia64 counter part of 18844:c820bf73a914.
Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
---
xen/arch/ia64/xen/domain.c | 5 +++
xen/arch/ia64/xen/hypercall.c | 32 +++++++++++++++++++
xen/arch/ia64/xen/irq.c | 69 +++++++++++++++++++++++++++++++++++++-----
xen/include/asm-ia64/domain.h | 4 ++
4 files changed, 102 insertions(+), 8 deletions(-)
diff -r c15577ad46f2 -r f0a9a58608a0 xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c Fri Dec 05 15:43:06 2008 +0900
+++ b/xen/arch/ia64/xen/domain.c Fri Dec 05 15:43:08 2008 +0900
@@ -1653,6 +1653,11 @@ int domain_relinquish_resources(struct d
/*fallthrough*/
case RELRES_mm_teardown:
+ if (d->arch.pirq_eoi_map != NULL) {
+ put_page(virt_to_page(d->arch.pirq_eoi_map));
+ d->arch.pirq_eoi_map = NULL;
+ }
+
/* Tear down shadow mode stuff. */
ret = mm_teardown(d);
if (ret != 0)
diff -r c15577ad46f2 -r f0a9a58608a0 xen/arch/ia64/xen/hypercall.c
--- a/xen/arch/ia64/xen/hypercall.c Fri Dec 05 15:43:06 2008 +0900
+++ b/xen/arch/ia64/xen/hypercall.c Fri Dec 05 15:43:08 2008 +0900
@@ -341,7 +341,39 @@ long do_physdev_op(int cmd, XEN_GUEST_HA
ret = -EFAULT;
if ( copy_from_guest(&eoi, arg, 1) != 0 )
break;
+ ret = -EINVAL;
+ if ( eoi.irq < 0 || eoi.irq >= NR_IRQS )
+ break;
+ if ( current->domain->arch.pirq_eoi_map )
+ evtchn_unmask(current->domain->pirq_to_evtchn[eoi.irq]);
ret = pirq_guest_eoi(current->domain, eoi.irq);
+ break;
+ }
+
+ case PHYSDEVOP_pirq_eoi_gmfn: {
+ struct physdev_pirq_eoi_gmfn info;
+ unsigned long mfn;
+
+ BUILD_BUG_ON(NR_IRQS > (PAGE_SIZE * 8));
+
+ ret = -EFAULT;
+ if ( copy_from_guest(&info, arg, 1) != 0 )
+ break;
+
+ ret = -EINVAL;
+ mfn = gmfn_to_mfn(current->domain, info.gmfn);
+ if ( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), current->domain) )
+ break;
+
+ if ( cmpxchg(¤t->domain->arch.pirq_eoi_map_mfn, 0, mfn) != 0 )
+ {
+ put_page(mfn_to_page(mfn));
+ ret = -EBUSY;
+ break;
+ }
+
+ current->domain->arch.pirq_eoi_map = mfn_to_virt(mfn);
+ ret = 0;
break;
}
diff -r c15577ad46f2 -r f0a9a58608a0 xen/arch/ia64/xen/irq.c
--- a/xen/arch/ia64/xen/irq.c Fri Dec 05 15:43:06 2008 +0900
+++ b/xen/arch/ia64/xen/irq.c Fri Dec 05 15:43:08 2008 +0900
@@ -312,16 +312,41 @@ typedef struct {
struct domain *guest[IRQ_MAX_GUESTS];
} irq_guest_action_t;
+static inline void set_pirq_eoi(struct domain *d, unsigned int irq)
+{
+ if ( d->arch.pirq_eoi_map )
+ set_bit(irq, d->arch.pirq_eoi_map);
+}
+
+static inline void clear_pirq_eoi(struct domain *d, unsigned int irq)
+{
+ if ( d->arch.pirq_eoi_map )
+ clear_bit(irq, d->arch.pirq_eoi_map);
+}
+
+static void _irq_guest_eoi(irq_desc_t *desc)
+{
+ irq_guest_action_t *action = (irq_guest_action_t *)desc->action;
+ unsigned int i, vector = desc - irq_desc;
+
+ if ( !(desc->status & IRQ_GUEST_EOI_PENDING) )
+ return;
+
+ for ( i = 0; i < action->nr_guests; ++i )
+ clear_pirq_eoi(action->guest[i], vector);
+
+ desc->status &= ~(IRQ_INPROGRESS|IRQ_GUEST_EOI_PENDING);
+ desc->handler->enable(vector);
+}
+
static struct timer irq_guest_eoi_timer[NR_IRQS];
static void irq_guest_eoi_timer_fn(void *data)
{
irq_desc_t *desc = data;
- unsigned vector = desc - irq_desc;
unsigned long flags;
spin_lock_irqsave(&desc->lock, flags);
- desc->status &= ~IRQ_INPROGRESS;
- desc->handler->enable(vector);
+ _irq_guest_eoi(desc);
spin_unlock_irqrestore(&desc->lock, flags);
}
@@ -355,8 +380,22 @@ void __do_IRQ_guest(int irq)
if ( already_pending == action->nr_guests )
{
+ stop_timer(&irq_guest_eoi_timer[irq]);
desc->handler->disable(irq);
- stop_timer(&irq_guest_eoi_timer[irq]);
+ desc->status |= IRQ_GUEST_EOI_PENDING;
+ for ( i = 0; i < already_pending; ++i )
+ {
+ d = action->guest[i];
+ set_pirq_eoi(d, irq);
+ /*
+ * Could check here whether the guest unmasked the event by now
+ * (or perhaps just re-issue the send_guest_pirq()), and if it
+ * can now accept the event,
+ * - clear all the pirq_eoi bits we already set,
+ * - re-enable the vector, and
+ * - skip the timer setup below.
+ */
+ }
init_timer(&irq_guest_eoi_timer[irq],
irq_guest_eoi_timer_fn, desc,
smp_processor_id());
set_timer(&irq_guest_eoi_timer[irq], NOW() + MILLISECS(1));
@@ -379,16 +418,25 @@ int pirq_guest_eoi(struct domain *d, int
int pirq_guest_eoi(struct domain *d, int irq)
{
irq_desc_t *desc;
+ irq_guest_action_t *action;
if ( (irq < 0) || (irq >= NR_IRQS) )
return -EINVAL;
desc = &irq_desc[irq];
spin_lock_irq(&desc->lock);
- if ( test_and_clear_bit(irq, &d->pirq_mask) &&
- (--((irq_guest_action_t *)desc->action)->in_flight == 0) )
- {
- ASSERT(((irq_guest_action_t*)desc->action)->ack_type ==
ACKTYPE_UNMASK);
+ action = (irq_guest_action_t *)desc->action;
+
+ if ( action->ack_type == ACKTYPE_NONE )
+ {
+ ASSERT(!test_bit(irq, d->pirq_mask));
+ stop_timer(&irq_guest_eoi_timer[irq]);
+ _irq_guest_eoi(desc);
+ }
+
+ if ( test_and_clear_bit(irq, &d->pirq_mask) && (--action->in_flight == 0) )
+ {
+ ASSERT(action->ack_type == ACKTYPE_UNMASK);
desc->handler->end(irq);
}
spin_unlock_irq(&desc->lock);
@@ -488,6 +536,11 @@ int pirq_guest_bind(struct vcpu *v, int
action->guest[action->nr_guests++] = v->domain;
+ if ( action->ack_type != ACKTYPE_NONE )
+ set_pirq_eoi(v->domain, irq);
+ else
+ clear_pirq_eoi(v->domain, irq);
+
out:
spin_unlock_irqrestore(&desc->lock, flags);
return rc;
diff -r c15577ad46f2 -r f0a9a58608a0 xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h Fri Dec 05 15:43:06 2008 +0900
+++ b/xen/include/asm-ia64/domain.h Fri Dec 05 15:43:08 2008 +0900
@@ -177,6 +177,10 @@ struct arch_domain {
/* Address of SAL emulator data */
struct xen_sal_data *sal_data;
+ /* Shared page for notifying that explicit PIRQ EOI is required. */
+ unsigned long *pirq_eoi_map;
+ unsigned long pirq_eoi_map_mfn;
+
/* Address of efi_runtime_services_t (placed in domain memory) */
void *efi_runtime;
/* Address of fpswa_interface_t (placed in domain memory) */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|