aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-03-26 12:26:45 +0000
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>2004-03-26 12:26:45 +0000
commitcaca24b294766e927d4624fe1fc534fd10f51801 (patch)
treed739261f7bcdfbddb8829a03596616f6d46a18db
parent9c127f7b32ec4b1f9a3cdbc6bd6f80dfcfbaa627 (diff)
downloadxen-caca24b294766e927d4624fe1fc534fd10f51801.tar.gz
xen-caca24b294766e927d4624fe1fc534fd10f51801.tar.bz2
xen-caca24b294766e927d4624fe1fc534fd10f51801.zip
bitkeeper revision 1.825.4.3 (40642185aZwwgLwBAies8HKAne40aw)
Many files: Adding physirq support to new Xen upcall interface. .del-physirq.c~e02f2ea038df07fa: Delete: xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c
-rw-r--r--.rootkeys1
-rw-r--r--xen/common/event_channel.c45
-rw-r--r--xen/common/physdev.c95
-rw-r--r--xen/include/hypervisor-ifs/dom0_ops.h2
-rw-r--r--xen/include/hypervisor-ifs/event_channel.h28
-rw-r--r--xen/include/hypervisor-ifs/physdev.h45
-rw-r--r--xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile2
-rw-r--r--xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c260
-rw-r--r--xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c175
-rw-r--r--xenolinux-2.4.25-sparse/include/asm-xen/irq.h15
10 files changed, 268 insertions, 400 deletions
diff --git a/.rootkeys b/.rootkeys
index 2caa01cd04..03b625759b 100644
--- a/.rootkeys
+++ b/.rootkeys
@@ -641,7 +641,6 @@
4051db8dJYX86ZCLA-WfTW2dAyrehw xenolinux-2.4.25-sparse/arch/xen/kernel/pci-i386.h
4051db91BenvDZEMZxQCGkQyJYoG5w xenolinux-2.4.25-sparse/arch/xen/kernel/pci-irq.c
4051db95N9N99FjsRwi49YKUNHWI8A xenolinux-2.4.25-sparse/arch/xen/kernel/pci-pc.c
-4051db99fbdTHgCpjywPCp7vjLCe7Q xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c
3e5a4e65IGt3WwQDNiL4h-gYWgNTWQ xenolinux-2.4.25-sparse/arch/xen/kernel/process.c
3e5a4e66tR-qJMLj3MppcKqmvuI2XQ xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c
3e5a4e66fWSTagLGU2P8BGFGRjhDiw xenolinux-2.4.25-sparse/arch/xen/kernel/signal.c
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index f5e48f366e..d0c0f5bba0 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -146,7 +146,7 @@ static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
int virq = bind->virq;
int port;
- if ( virq >= NR_VIRQS )
+ if ( virq >= ARRAY_SIZE(p->virq_to_evtchn) )
return -EINVAL;
spin_lock(&p->event_channel_lock);
@@ -177,6 +177,37 @@ static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
}
+static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
+{
+ struct task_struct *p = current;
+ int pirq = bind->pirq;
+ int port;
+
+ if ( pirq >= ARRAY_SIZE(p->pirq_to_evtchn) )
+ return -EINVAL;
+
+ spin_lock(&p->event_channel_lock);
+
+ if ( ((port = p->pirq_to_evtchn[pirq]) != 0) ||
+ ((port = get_free_port(p)) < 0) )
+ goto out;
+
+ p->event_channel[port].state = ECS_PIRQ;
+ p->event_channel[port].u.pirq = pirq;
+
+ p->pirq_to_evtchn[pirq] = port;
+
+ out:
+ spin_unlock(&p->event_channel_lock);
+
+ if ( port < 0 )
+ return port;
+
+ bind->port = port;
+ return 0;
+}
+
+
static long __evtchn_close(struct task_struct *p1, int port1)
{
struct task_struct *p2 = NULL;
@@ -396,13 +427,19 @@ long do_event_channel_op(evtchn_op_t *uop)
{
case EVTCHNOP_bind_interdomain:
rc = evtchn_bind_interdomain(&op.u.bind_interdomain);
- if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
+ if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
rc = -EFAULT; /* Cleaning up here would be a mess! */
break;
case EVTCHNOP_bind_virq:
rc = evtchn_bind_virq(&op.u.bind_virq);
- if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
+ if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
+ rc = -EFAULT; /* Cleaning up here would be a mess! */
+ break;
+
+ case EVTCHNOP_bind_pirq:
+ rc = evtchn_bind_pirq(&op.u.bind_pirq);
+ if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
rc = -EFAULT; /* Cleaning up here would be a mess! */
break;
@@ -416,7 +453,7 @@ long do_event_channel_op(evtchn_op_t *uop)
case EVTCHNOP_status:
rc = evtchn_status(&op.u.status);
- if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
+ if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
rc = -EFAULT;
break;
diff --git a/xen/common/physdev.c b/xen/common/physdev.c
index da22f88cfe..08da1b5206 100644
--- a/xen/common/physdev.c
+++ b/xen/common/physdev.c
@@ -601,7 +601,7 @@ static void end_virt_irq (unsigned int i)
* - shared interrupts are not allowed for now
* - we change the hw_irq handler to something else
*/
-static long pci_request_irq(int irq)
+static long pirq_request(int irq)
{
int err;
phys_dev_t *pdev = NULL, *t;
@@ -685,7 +685,7 @@ static long pci_request_irq(int irq)
return 0;
}
-static long pci_free_irq(int irq)
+long pirq_free(int irq)
{
phys_dev_t *pdev;
@@ -719,55 +719,12 @@ static long pci_free_irq(int irq)
return 0;
}
-static long pci_enable_irq(int irq)
+static long pci_unmask_irq(void)
{
- /* XXX not sure we need this */
- /* guest can enable phys_irq event for now */
- return 0;
-}
-
-static long pci_disable_irq(int irq)
-{
- /* XXX not sure we need this */
- /* guest can disable phys_irq event for now */
- return 0;
-}
-
-static long pci_finished_irq(int irq)
-{
- phys_dev_t *pdev;
-
- if ( !(pdev = irqs[irq]) )
- {
- printk("finished_irq called for unregistered irq %d\n", irq);
- return -EINVAL;
- }
-
- if ( pdev->owner != current )
- {
- printk("finished_irq called dom not owning irq %d\n", irq);
- return -EPERM;
- }
-
- if ( !test_bit(ST_IRQ_DELIVERED, &pdev->state) )
- {
- printk("finished_irq called for undelivered irq %d\n", irq);
- return -EINVAL;
- }
-
-#if 0 /* XXX KAF: do we need this? */
- if ( test_bit(irq, &current->shared_info->physirq_pend) )
- {
- printk("finished_irq called for un-acknowleged irq %d\n", irq);
- return -EINVAL;
- }
-#endif
-
+#if 0
clear_bit(ST_IRQ_DELIVERED, &pdev->state);
-
- /* call original end handler */
pdev->orig_handler->end(irq);
-
+#endif
return 0;
}
@@ -786,43 +743,27 @@ long do_physdev_op(physdev_op_t *uop)
switch ( op.cmd )
{
case PHYSDEVOP_CFGREG_READ:
- ret = pci_cfgreg_read (op.u.cfg_read.seg, op.u.cfg_read.bus,
- op.u.cfg_read.dev, op.u.cfg_read.func,
- op.u.cfg_read.reg, op.u.cfg_read.len,
- &op.u.cfg_read.value);
+ ret = pci_cfgreg_read(op.u.cfg_read.seg, op.u.cfg_read.bus,
+ op.u.cfg_read.dev, op.u.cfg_read.func,
+ op.u.cfg_read.reg, op.u.cfg_read.len,
+ &op.u.cfg_read.value);
break;
case PHYSDEVOP_CFGREG_WRITE:
- ret = pci_cfgreg_write (op.u.cfg_write.seg, op.u.cfg_write.bus,
- op.u.cfg_write.dev, op.u.cfg_write.func,
- op.u.cfg_write.reg, op.u.cfg_write.len,
- op.u.cfg_write.value);
+ ret = pci_cfgreg_write(op.u.cfg_write.seg, op.u.cfg_write.bus,
+ op.u.cfg_write.dev, op.u.cfg_write.func,
+ op.u.cfg_write.reg, op.u.cfg_write.len,
+ op.u.cfg_write.value);
break;
case PHYSDEVOP_FIND_IRQ:
- ret = pci_find_irq (op.u.find_irq.seg, op.u.find_irq.bus,
- op.u.find_irq.dev, op.u.find_irq.func,
- &op.u.find_irq.irq);
- break;
-
- case PHYSDEVOP_REQUEST_IRQ:
- ret = pci_request_irq (op.u.request_irq.irq);
- break;
-
- case PHYSDEVOP_FREE_IRQ:
- ret = pci_free_irq (op.u.free_irq.irq);
- break;
-
- case PHYSDEVOP_ENABLE_IRQ:
- ret = pci_enable_irq (op.u.enable_irq.irq);
- break;
-
- case PHYSDEVOP_DISABLE_IRQ:
- ret = pci_disable_irq (op.u.disable_irq.irq);
+ ret = pci_find_irq(op.u.find_irq.seg, op.u.find_irq.bus,
+ op.u.find_irq.dev, op.u.find_irq.func,
+ &op.u.find_irq.irq);
break;
- case PHYSDEVOP_FINISHED_IRQ:
- ret = pci_finished_irq (op.u.finished_irq.irq);
+ case PHYSDEVOP_UNMASK_IRQ:
+ ret = pci_unmask_irq();
break;
default:
diff --git a/xen/include/hypervisor-ifs/dom0_ops.h b/xen/include/hypervisor-ifs/dom0_ops.h
index 8574f02531..ce748d5d31 100644
--- a/xen/include/hypervisor-ifs/dom0_ops.h
+++ b/xen/include/hypervisor-ifs/dom0_ops.h
@@ -18,7 +18,7 @@
* This makes sure that old versions of dom0 tools will stop working in a
* well-defined way (rather than crashing the machine, for instance).
*/
-#define DOM0_INTERFACE_VERSION 0xAAAA0009
+#define DOM0_INTERFACE_VERSION 0xAAAA000A
#define MAX_CMD_LEN 256
#define MAX_DOMAIN_NAME 16
diff --git a/xen/include/hypervisor-ifs/event_channel.h b/xen/include/hypervisor-ifs/event_channel.h
index 6fae72cc38..fdc4eaeb1b 100644
--- a/xen/include/hypervisor-ifs/event_channel.h
+++ b/xen/include/hypervisor-ifs/event_channel.h
@@ -30,7 +30,7 @@ typedef struct evtchn_bind_interdomain
* NOTES:
* 1. A virtual IRQ may be bound to at most one event channel per domain.
*/
-#define EVTCHNOP_bind_virq 1
+#define EVTCHNOP_bind_virq 1
typedef struct evtchn_bind_virq
{
/* IN parameters. */
@@ -40,6 +40,21 @@ typedef struct evtchn_bind_virq
} evtchn_bind_virq_t;
/*
+ * EVTCHNOP_bind_pirq: Bind a local event channel to IRQ <irq>.
+ * NOTES:
+ * 1. A physical IRQ may be bound to at most one event channel per domain.
+ * 2. Only a sufficiently-privileged domain may bind to a physical IRQ.
+ */
+#define EVTCHNOP_bind_pirq 2
+typedef struct evtchn_bind_pirq
+{
+ /* IN parameters. */
+ int pirq;
+ /* OUT parameters. */
+ int port;
+} evtchn_bind_pirq_t;
+
+/*
* EVTCHNOP_close: Close the communication channel which has an endpoint at
* <dom, port>.
* NOTES:
@@ -47,7 +62,7 @@ typedef struct evtchn_bind_virq
* 2. Only a sufficiently-privileged domain may close an event channel
* for which <dom> is not DOMID_SELF.
*/
-#define EVTCHNOP_close 2
+#define EVTCHNOP_close 3
typedef struct evtchn_close
{
/* IN parameters. */
@@ -60,7 +75,7 @@ typedef struct evtchn_close
* EVTCHNOP_send: Send an event to the remote end of the channel whose local
* endpoint is <DOMID_SELF, local_port>.
*/
-#define EVTCHNOP_send 3
+#define EVTCHNOP_send 4
typedef struct evtchn_send
{
/* IN parameters. */
@@ -76,7 +91,7 @@ typedef struct evtchn_send
* 2. Only a sufficiently-privileged domain may obtain the status of an event
* channel for which <dom> is not DOMID_SELF.
*/
-#define EVTCHNOP_status 4
+#define EVTCHNOP_status 5
typedef struct evtchn_status
{
/* IN parameters */
@@ -86,8 +101,8 @@ typedef struct evtchn_status
#define EVTCHNSTAT_closed 0 /* Chennel is not in use. */
#define EVTCHNSTAT_unbound 1 /* Channel is not bound to a source. */
#define EVTCHNSTAT_interdomain 2 /* Channel is connected to remote domain. */
-#define EVTCHNSTAT_pirq 3 /* Channel is bound to a phys IRQ line. */
-#define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */
+#define EVTCHNSTAT_pirq 3 /* Channel is bound to a phys IRQ line. */
+#define EVTCHNSTAT_virq 4 /* Channel is bound to a virtual IRQ line */
int status;
union {
int __none; /* EVTCHNSTAT_closed, EVTCHNSTAT_unbound */
@@ -106,6 +121,7 @@ typedef struct evtchn_op
union {
evtchn_bind_interdomain_t bind_interdomain;
evtchn_bind_virq_t bind_virq;
+ evtchn_bind_pirq_t bind_pirq;
evtchn_close_t close;
evtchn_send_t send;
evtchn_status_t status;
diff --git a/xen/include/hypervisor-ifs/physdev.h b/xen/include/hypervisor-ifs/physdev.h
index 925023056c..383bb13097 100644
--- a/xen/include/hypervisor-ifs/physdev.h
+++ b/xen/include/hypervisor-ifs/physdev.h
@@ -19,11 +19,7 @@
#define PHYSDEVOP_CFGREG_READ 0
#define PHYSDEVOP_CFGREG_WRITE 1
#define PHYSDEVOP_FIND_IRQ 2
-#define PHYSDEVOP_REQUEST_IRQ 3
-#define PHYSDEVOP_FREE_IRQ 4
-#define PHYSDEVOP_ENABLE_IRQ 5
-#define PHYSDEVOP_DISABLE_IRQ 6
-#define PHYSDEVOP_FINISHED_IRQ 7
+#define PHYSDEVOP_UNMASK_IRQ 3
/* read pci config */
typedef struct physdevop_cfgreg_read_st
@@ -32,8 +28,8 @@ typedef struct physdevop_cfgreg_read_st
int bus; /* IN */
int dev; /* IN */
int func; /* IN */
- int reg; /* IN */
- int len; /* IN */
+ int reg; /* IN */
+ int len; /* IN */
u32 value; /* OUT */
} physdevop_cfgreg_read_t;
@@ -59,36 +55,6 @@ typedef struct physdevop_find_irq_st
u32 irq; /* OUT */
} physdevop_find_irq_t;
-/* request physical IRQ to be routed to guest */
-typedef struct physdevop_request_irq_st
-{
- u32 irq; /* IN */
-} physdevop_request_irq_t;
-
-/* stop routing physical interrupts to guest */
-typedef struct physdevop_free_irq_st
-{
- u32 irq; /* IN */
-} physdevop_free_irq_t;
-
-/* enable IRQ for the caller */
-typedef struct physdevop_enable_irq_st
-{
- u32 irq; /* IN */
-} physdevop_enable_irq_t;
-
-/* disable interrupts */
-typedef struct physdevop_disable_irq_st
-{
- u32 irq; /* IN */
-} physdevop_disable_irq_t;
-
-typedef struct physdevop_finished_irq_st
-{
- u32 irq; /* IN */
-} physdevop_finished_irq_t;
-
-
typedef struct _physdev_op_st
{
unsigned long cmd;
@@ -99,11 +65,6 @@ typedef struct _physdev_op_st
physdevop_cfgreg_read_t cfg_read;
physdevop_cfgreg_write_t cfg_write;
physdevop_find_irq_t find_irq;
- physdevop_request_irq_t request_irq;
- physdevop_free_irq_t free_irq;
- physdevop_enable_irq_t enable_irq;
- physdevop_disable_irq_t disable_irq;
- physdevop_finished_irq_t finished_irq;
} u;
} physdev_op_t;
diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile b/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile
index 9f86b6d297..5abf0a0d62 100644
--- a/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile
+++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile
@@ -10,7 +10,7 @@ export-objs := i386_ksyms.o
obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o \
- i386_ksyms.o i387.o evtchn.o physirq.o pci-dma.o
+ i386_ksyms.o i387.o evtchn.o pci-dma.o
ifdef CONFIG_PCI
obj-y += pci-i386.o pci-pc.o pci-irq.o
diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c b/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c
index 266867fc74..4eb83c4b4c 100644
--- a/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c
+++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c
@@ -17,20 +17,23 @@
#include <asm/synch_bitops.h>
#include <asm/hypervisor.h>
#include <asm/hypervisor-ifs/event_channel.h>
-
-/* Dynamic IRQ <-> event-channel mappings. */
-static int evtchn_to_dynirq[1024];
-static int dynirq_to_evtchn[NR_IRQS];
-
-/* Dynamic IRQ <-> VIRQ mapping. */
-static int virq_to_dynirq[NR_VIRQS];
+#include <asm/hypervisor-ifs/physdev.h>
/*
- * Reference counts for bindings to dynamic IRQs.
- * NB. This array is referenced with respect to DYNIRQ_BASE!
+ * This lock protects updates to the following mapping and reference-count
+ * arrays. The lock does not need to be acquired to read the mapping tables.
*/
-static int dynirq_bindcount[NR_DYNIRQS];
-static spinlock_t dynirq_lock;
+static spinlock_t irq_mapping_update_lock;
+
+/* IRQ <-> event-channel mappings. */
+static int evtchn_to_irq[NR_EVENT_CHANNELS];
+static int irq_to_evtchn[NR_IRQS];
+
+/* IRQ <-> VIRQ mapping. */
+static int virq_to_irq[NR_VIRQS];
+
+/* Reference counts for bindings to IRQs. */
+static int irq_bindcount[NR_IRQS];
/* Upcall to generic IRQ layer. */
extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs);
@@ -39,7 +42,7 @@ static void evtchn_handle_normal(shared_info_t *s, struct pt_regs *regs)
{
unsigned long l1, l2;
unsigned int l1i, l2i, port;
- int dynirq;
+ int irq;
l1 = xchg(&s->evtchn_pending_sel, 0);
while ( (l1i = ffs(l1)) != 0 )
@@ -54,8 +57,8 @@ static void evtchn_handle_normal(shared_info_t *s, struct pt_regs *regs)
l2 &= ~(1 << l2i);
port = (l1i << 5) + l2i;
- if ( (dynirq = evtchn_to_dynirq[port]) != -1 )
- do_IRQ(dynirq + DYNIRQ_BASE, regs);
+ if ( (irq = evtchn_to_irq[port]) != -1 )
+ do_IRQ(irq, regs);
else
evtchn_device_upcall(port, 0);
}
@@ -66,7 +69,7 @@ static void evtchn_handle_exceptions(shared_info_t *s, struct pt_regs *regs)
{
unsigned long l1, l2;
unsigned int l1i, l2i, port;
- int dynirq;
+ int irq;
l1 = xchg(&s->evtchn_exception_sel, 0);
while ( (l1i = ffs(l1)) != 0 )
@@ -81,10 +84,9 @@ static void evtchn_handle_exceptions(shared_info_t *s, struct pt_regs *regs)
l2 &= ~(1 << l2i);
port = (l1i << 5) + l2i;
- if ( (dynirq = evtchn_to_dynirq[port]) != -1 )
+ if ( (irq = evtchn_to_irq[port]) != -1 )
{
- printk(KERN_ALERT "Error on IRQ line %d!\n",
- dynirq + DYNIRQ_BASE);
+ printk(KERN_ALERT "Error on IRQ line %d!\n", irq);
synch_clear_bit(port, &s->evtchn_exception[0]);
}
else
@@ -112,28 +114,28 @@ void evtchn_do_upcall(struct pt_regs *regs)
}
-static int find_unbound_dynirq(void)
+static int find_unbound_irq(void)
{
- int i;
+ int irq;
- for ( i = 0; i < NR_DYNIRQS; i++ )
- if ( dynirq_bindcount[i] == 0 )
+ for ( irq = 0; irq < NR_IRQS; irq++ )
+ if ( irq_bindcount[irq] == 0 )
break;
- if ( i == NR_DYNIRQS )
+ if ( irq == NR_IRQS )
BUG();
- return i;
+ return irq;
}
int bind_virq_to_irq(int virq)
{
evtchn_op_t op;
- int evtchn, dynirq;
+ int evtchn, irq;
- spin_lock(&dynirq_lock);
+ spin_lock(&irq_mapping_update_lock);
- if ( (dynirq = virq_to_dynirq[virq]) == -1 )
+ if ( (irq = virq_to_irq[virq]) == -1 )
{
op.cmd = EVTCHNOP_bind_virq;
op.u.bind_virq.virq = virq;
@@ -141,29 +143,29 @@ int bind_virq_to_irq(int virq)
BUG();
evtchn = op.u.bind_virq.port;
- dynirq = find_unbound_dynirq();
- evtchn_to_dynirq[evtchn] = dynirq;
- dynirq_to_evtchn[dynirq] = evtchn;
+ irq = find_unbound_irq();
+ evtchn_to_irq[evtchn] = irq;
+ irq_to_evtchn[irq] = evtchn;
- virq_to_dynirq[virq] = dynirq;
+ virq_to_irq[virq] = irq;
}
- dynirq_bindcount[dynirq]++;
+ irq_bindcount[irq]++;
- spin_unlock(&dynirq_lock);
+ spin_unlock(&irq_mapping_update_lock);
- return dynirq + DYNIRQ_BASE;
+ return irq;
}
void unbind_virq_from_irq(int virq)
{
evtchn_op_t op;
- int dynirq = virq_to_dynirq[virq];
- int evtchn = dynirq_to_evtchn[dynirq];
+ int irq = virq_to_irq[virq];
+ int evtchn = irq_to_evtchn[irq];
- spin_lock(&dynirq_lock);
+ spin_lock(&irq_mapping_update_lock);
- if ( --dynirq_bindcount[dynirq] == 0 )
+ if ( --irq_bindcount[irq] == 0 )
{
op.cmd = EVTCHNOP_close;
op.u.close.dom = DOMID_SELF;
@@ -171,47 +173,47 @@ void unbind_virq_from_irq(int virq)
if ( HYPERVISOR_event_channel_op(&op) != 0 )
BUG();
- evtchn_to_dynirq[evtchn] = -1;
- dynirq_to_evtchn[dynirq] = -1;
- virq_to_dynirq[virq] = -1;
+ evtchn_to_irq[evtchn] = -1;
+ irq_to_evtchn[irq] = -1;
+ virq_to_irq[virq] = -1;
}
- spin_unlock(&dynirq_lock);
+ spin_unlock(&irq_mapping_update_lock);
}
int bind_evtchn_to_irq(int evtchn)
{
- int dynirq;
+ int irq;
- spin_lock(&dynirq_lock);
+ spin_lock(&irq_mapping_update_lock);
- if ( (dynirq = evtchn_to_dynirq[evtchn]) == -1 )
+ if ( (irq = evtchn_to_irq[evtchn]) == -1 )
{
- dynirq = find_unbound_dynirq();
- evtchn_to_dynirq[evtchn] = dynirq;
- dynirq_to_evtchn[dynirq] = evtchn;
+ irq = find_unbound_irq();
+ evtchn_to_irq[evtchn] = irq;
+ irq_to_evtchn[irq] = evtchn;
}
- dynirq_bindcount[dynirq]++;
+ irq_bindcount[irq]++;
- spin_unlock(&dynirq_lock);
+ spin_unlock(&irq_mapping_update_lock);
- return dynirq + DYNIRQ_BASE;
+ return irq;
}
void unbind_evtchn_from_irq(int evtchn)
{
- int dynirq = evtchn_to_dynirq[evtchn];
+ int irq = evtchn_to_irq[evtchn];
- spin_lock(&dynirq_lock);
+ spin_lock(&irq_mapping_update_lock);
- if ( --dynirq_bindcount[dynirq] == 0 )
+ if ( --irq_bindcount[irq] == 0 )
{
- evtchn_to_dynirq[evtchn] = -1;
- dynirq_to_evtchn[dynirq] = -1;
+ evtchn_to_irq[evtchn] = -1;
+ irq_to_evtchn[irq] = -1;
}
- spin_unlock(&dynirq_lock);
+ spin_unlock(&irq_mapping_update_lock);
}
@@ -221,41 +223,35 @@ void unbind_evtchn_from_irq(int evtchn)
static unsigned int startup_dynirq(unsigned int irq)
{
- int dynirq = irq - DYNIRQ_BASE;
- unmask_evtchn(dynirq_to_evtchn[dynirq]);
+ unmask_evtchn(irq_to_evtchn[irq]);
return 0;
}
static void shutdown_dynirq(unsigned int irq)
{
- int dynirq = irq - DYNIRQ_BASE;
- mask_evtchn(dynirq_to_evtchn[dynirq]);
+ mask_evtchn(irq_to_evtchn[irq]);
}
static void enable_dynirq(unsigned int irq)
{
- int dynirq = irq - DYNIRQ_BASE;
- unmask_evtchn(dynirq_to_evtchn[dynirq]);
+ unmask_evtchn(irq_to_evtchn[irq]);
}
static void disable_dynirq(unsigned int irq)
{
- int dynirq = irq - DYNIRQ_BASE;
- mask_evtchn(dynirq_to_evtchn[dynirq]);
+ mask_evtchn(irq_to_evtchn[irq]);
}
static void ack_dynirq(unsigned int irq)
{
- int dynirq = irq - DYNIRQ_BASE;
- mask_evtchn(dynirq_to_evtchn[dynirq]);
- clear_evtchn(dynirq_to_evtchn[dynirq]);
+ mask_evtchn(irq_to_evtchn[irq]);
+ clear_evtchn(irq_to_evtchn[irq]);
}
static void end_dynirq(unsigned int irq)
{
- int dynirq = irq - DYNIRQ_BASE;
if ( !(irq_desc[irq].status & IRQ_DISABLED) )
- unmask_evtchn(dynirq_to_evtchn[dynirq]);
+ unmask_evtchn(irq_to_evtchn[irq]);
}
static struct hw_interrupt_type dynirq_type = {
@@ -269,6 +265,87 @@ static struct hw_interrupt_type dynirq_type = {
NULL
};
+static inline void pirq_unmask_notify(int pirq)
+{
+ physdev_op_t op;
+ op.cmd = PHYSDEVOP_UNMASK_IRQ;
+ (void)HYPERVISOR_physdev_op(&op);
+}
+
+static unsigned int startup_pirq(unsigned int irq)
+{
+ evtchn_op_t op;
+ int evtchn;
+
+ op.cmd = EVTCHNOP_bind_pirq;
+ op.u.bind_pirq.pirq = irq;
+ if ( HYPERVISOR_event_channel_op(&op) != 0 )
+ BUG();
+ evtchn = op.u.bind_virq.port;
+
+ evtchn_to_irq[evtchn] = irq;
+ irq_to_evtchn[irq] = evtchn;
+
+ unmask_evtchn(evtchn);
+ pirq_unmask_notify(irq_to_pirq(irq));
+
+ return 0;
+}
+
+static void shutdown_pirq(unsigned int irq)
+{
+ evtchn_op_t op;
+ int evtchn = irq_to_evtchn[irq];
+
+ mask_evtchn(evtchn);
+
+ op.cmd = EVTCHNOP_close;
+ op.u.close.dom = DOMID_SELF;
+ op.u.close.port = evtchn;
+ if ( HYPERVISOR_event_channel_op(&op) != 0 )
+ BUG();
+
+ evtchn_to_irq[evtchn] = -1;
+ irq_to_evtchn[irq] = -1;
+}
+
+static void enable_pirq(unsigned int irq)
+{
+ unmask_evtchn(irq_to_evtchn[irq]);
+ pirq_unmask_notify(irq_to_pirq(irq));
+}
+
+static void disable_pirq(unsigned int irq)
+{
+ mask_evtchn(irq_to_evtchn[irq]);
+}
+
+static void ack_pirq(unsigned int irq)
+{
+ mask_evtchn(irq_to_evtchn[irq]);
+ clear_evtchn(irq_to_evtchn[irq]);
+}
+
+static void end_pirq(unsigned int irq)
+{
+ if ( !(irq_desc[irq].status & IRQ_DISABLED) )
+ {
+ unmask_evtchn(irq_to_evtchn[irq]);
+ pirq_unmask_notify(irq_to_pirq(irq));
+ }
+}
+
+static struct hw_interrupt_type pirq_type = {
+ "Phys-irq",
+ startup_pirq,
+ shutdown_pirq,
+ enable_pirq,
+ disable_pirq,
+ ack_pirq,
+ end_pirq,
+ NULL
+};
+
static void error_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
printk(KERN_ALERT "unexpected VIRQ_ERROR trap to vector %d\n", irq);
@@ -287,32 +364,41 @@ void __init init_IRQ(void)
{
int i;
+ spin_lock_init(&irq_mapping_update_lock);
+
+ /* No VIRQ -> IRQ mappings. */
for ( i = 0; i < NR_VIRQS; i++ )
- virq_to_dynirq[i] = -1;
+ virq_to_irq[i] = -1;
- for ( i = 0; i < 1024; i++ )
- evtchn_to_dynirq[i] = -1;
+ /* No event-channel -> IRQ mappings. */
+ for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
+ evtchn_to_irq[i] = -1;
+
+ /* No IRQ -> event-channel mappings. */
+ for ( i = 0; i < NR_IRQS; i++ )
+ irq_to_evtchn[i] = -1;
for ( i = 0; i < NR_DYNIRQS; i++ )
{
- dynirq_to_evtchn[i] = -1;
- dynirq_bindcount[i] = 0;
- }
+ /* Dynamic IRQ space is currently unbound. Zero the refcnts. */
+ irq_bindcount[dynirq_to_irq(i)] = 0;
- spin_lock_init(&dynirq_lock);
+ irq_desc[dynirq_to_irq(i)].status = IRQ_DISABLED;
+ irq_desc[dynirq_to_irq(i)].action = 0;
+ irq_desc[dynirq_to_irq(i)].depth = 1;
+ irq_desc[dynirq_to_irq(i)].handler = &dynirq_type;
+ }
- for ( i = 0; i < NR_DYNIRQS; i++ )
+ for ( i = 0; i < NR_PIRQS; i++ )
{
- irq_desc[i + DYNIRQ_BASE].status = IRQ_DISABLED;
- irq_desc[i + DYNIRQ_BASE].action = 0;
- irq_desc[i + DYNIRQ_BASE].depth = 1;
- irq_desc[i + DYNIRQ_BASE].handler = &dynirq_type;
+ /* Phys IRQ space is statically bound (1:1 mapping). Nail refcnts. */
+ irq_bindcount[pirq_to_irq(i)] = 1;
+
+ irq_desc[pirq_to_irq(i)].status = IRQ_DISABLED;
+ irq_desc[pirq_to_irq(i)].action = 0;
+ irq_desc[pirq_to_irq(i)].depth = 1;
+ irq_desc[pirq_to_irq(i)].handler = &pirq_type;
}
(void)setup_irq(bind_virq_to_irq(VIRQ_ERROR), &error_action);
-
-#ifdef CONFIG_PCI
- /* Also initialise the physical IRQ handlers. */
- physirq_init();
-#endif
}
diff --git a/xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c b/xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c
deleted file mode 100644
index 7c04c9d9dc..0000000000
--- a/xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
- ****************************************************************************
- * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
- ****************************************************************************
- *
- * File: physirq.c
- * Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
- * Date: Mar 2004
- *
- * Description: guests may receive virtual interrupts directly
- * corresponding to physical interrupts. these virtual
- * interrupts require special handling provided
- * by the virq irq type.
- */
-
-#ifdef CONFIG_PCI
-
-#include <linux/config.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/hypervisor.h>
-#include <asm/system.h>
-
-#include <linux/irq.h>
-#include <linux/sched.h>
-
-#include <asm/hypervisor-ifs/hypervisor-if.h>
-#include <asm/hypervisor-ifs/physdev.h>
-
-static void physirq_interrupt(int irq, void *unused, struct pt_regs *ptregs);
-
-static int setup_event_handler = 0;
-
-static unsigned int startup_physirq_event(unsigned int irq)
-{
- physdev_op_t op;
- int err;
-
- printk("startup_physirq_event %d\n", irq);
-
- /*
- * install a interrupt handler for physirq event when called first time
- * we actually are never executing the handler as _EVENT_PHYSIRQ is
- * handled specially in hypervisor.c But we need to enable the event etc.
- */
- if ( !setup_event_handler )
- {
- printk("startup_physirq_event %d: setup event handler\n", irq);
- /* set up a event handler to demux virtualised physical interrupts */
- err = request_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ), physirq_interrupt,
- SA_SAMPLE_RANDOM, "physirq", NULL);
- if ( err )
- {
- printk(KERN_WARNING "Could not allocate physirq interrupt\n");
- return err;
- }
- setup_event_handler = 1;
- }
-
- /*
- * request the irq from hypervisor
- */
- op.cmd = PHYSDEVOP_REQUEST_IRQ;
- op.u.request_irq.irq = irq;
- if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
- {
- printk(KERN_ALERT "could not get IRQ %d from Xen\n", irq);
- return err;
- }
- return 0;
-}
-/*
- * This is a dummy interrupt handler.
- * It should never be called. events for physical interrupts are handled
- * differently in hypervisor.c
- */
-static void physirq_interrupt(int irq, void *unused, struct pt_regs *ptregs)
-{
- printk("XXX This should never be called!");
-}
-
-
-/*
- * IRQ is not needed anymore.
- */
-static void shutdown_physirq_event(unsigned int irq)
-{
- physdev_op_t op;
- int err;
-
- printk("shutdown_phys_irq called.");
-
- /*
- * tell hypervisor
- */
- op.cmd = PHYSDEVOP_FREE_IRQ;
- op.u.free_irq.irq = irq;
- if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
- {
- printk(KERN_ALERT "could not free IRQ %d\n", irq);
- return;
- }
- return;
-}
-
-
-static void enable_physirq_event(unsigned int irq)
-{
- /* XXX just enable all phys interrupts for now */
- enable_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ));
-}
-
-static void disable_physirq_event(unsigned int irq)
-{
- /* XXX just disable all phys interrupts for now */
- disable_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ));
-}
-
-static void ack_physirq_event(unsigned int irq)
-{
- /* clear bit */
- if ( irq <= 0 || irq >= 32 )
- {
- printk("wrong irq %d\n", irq);
- }
-
- clear_bit(irq, &HYPERVISOR_shared_info->physirq_pend);
-}
-
-static void end_physirq_event(unsigned int irq)
-{
- int err;
- physdev_op_t op;
-
- /* call hypervisor */
- op.cmd = PHYSDEVOP_FINISHED_IRQ;
- op.u.finished_irq.irq = irq;
- if ( (err = HYPERVISOR_physdev_op(&op)) != 0 )
- {
- printk(KERN_ALERT "could not finish IRQ %d\n", irq);
- return;
- }
- return;
-}
-
-static struct hw_interrupt_type physirq_irq_type = {
- "physical-irq",
- startup_physirq_event,
- shutdown_physirq_event,
- enable_physirq_event,
- disable_physirq_event,
- ack_physirq_event,
- end_physirq_event,
- NULL
-};
-
-
-
-void __init physirq_init(void)
-{
- int i;
-
- printk("Initialise irq handlers [%d-%d] for physical interrupts.\n",
- PHYS_IRQ_BASE, PHYS_IRQ_BASE+NR_PHYS_IRQS-1);
-
- for ( i = 0; i < NR_PHYS_IRQS; i++ )
- {
- irq_desc[i + PHYS_IRQ_BASE].status = IRQ_DISABLED;
- irq_desc[i + PHYS_IRQ_BASE].action = 0;
- irq_desc[i + PHYS_IRQ_BASE].depth = 1;
- irq_desc[i + PHYS_IRQ_BASE].handler = &physirq_irq_type;
- }
-}
-
-#endif
diff --git a/xenolinux-2.4.25-sparse/include/asm-xen/irq.h b/xenolinux-2.4.25-sparse/include/asm-xen/irq.h
index 6d175ce6ab..a05b99640e 100644
--- a/xenolinux-2.4.25-sparse/include/asm-xen/irq.h
+++ b/xenolinux-2.4.25-sparse/include/asm-xen/irq.h
@@ -32,7 +32,11 @@
#define NR_IRQS (NR_PIRQS + NR_DYNIRQS)
-extern void physirq_init(void);
+#define pirq_to_irq(_x) ((_x) + PIRQ_BASE)
+#define irq_to_pirq(_x) ((_x) - PIRQ_BASE)
+
+#define dynirq_to_irq(_x) ((_x) + DYNIRQ_BASE)
+#define irq_to_dynirq(_x) ((_x) - DYNIRQ_BASE)
/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
extern int bind_virq_to_irq(int virq);
@@ -40,14 +44,13 @@ extern void unbind_virq_from_irq(int virq);
extern int bind_evtchn_to_irq(int evtchn);
extern void unbind_evtchn_from_irq(int evtchn);
-#define irq_cannonicalize(_irq) (_irq)
+static __inline__ int irq_cannonicalize(int irq)
+{
+ return (irq == 2) ? 9 : irq;
+}
extern void disable_irq(unsigned int);
extern void disable_irq_nosync(unsigned int);
extern void enable_irq(unsigned int);
-#ifdef CONFIG_X86_LOCAL_APIC
-#define ARCH_HAS_NMI_WATCHDOG /* See include/linux/nmi.h */
-#endif
-
#endif /* _ASM_IRQ_H */