aboutsummaryrefslogtreecommitdiffstats
path: root/xenolinux-2.4.24-sparse/arch/xeno/kernel/hypervisor.c
diff options
context:
space:
mode:
Diffstat (limited to 'xenolinux-2.4.24-sparse/arch/xeno/kernel/hypervisor.c')
-rw-r--r--xenolinux-2.4.24-sparse/arch/xeno/kernel/hypervisor.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/xenolinux-2.4.24-sparse/arch/xeno/kernel/hypervisor.c b/xenolinux-2.4.24-sparse/arch/xeno/kernel/hypervisor.c
new file mode 100644
index 0000000000..3f414e9876
--- /dev/null
+++ b/xenolinux-2.4.24-sparse/arch/xeno/kernel/hypervisor.c
@@ -0,0 +1,128 @@
+/******************************************************************************
+ * hypervisor.c
+ *
+ * Communication to/from hypervisor.
+ *
+ * Copyright (c) 2002, K A Fraser
+ */
+
+#include <linux/config.h>
+#include <asm/atomic.h>
+#include <linux/irq.h>
+#include <asm/hypervisor.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+
+multicall_entry_t multicall_list[8];
+int nr_multicall_ents = 0;
+
+static unsigned long event_mask = 0;
+
+void frobb(void) {}
+
+void do_hypervisor_callback(struct pt_regs *regs)
+{
+ unsigned long events, flags;
+ shared_info_t *shared = HYPERVISOR_shared_info;
+
+ do {
+ /* Specialised local_irq_save(). */
+ flags = test_and_clear_bit(EVENTS_MASTER_ENABLE_BIT,
+ &shared->events_mask);
+ barrier();
+
+ events = xchg(&shared->events, 0);
+ events &= event_mask;
+
+ __asm__ __volatile__ (
+ " push %1 ;"
+ " sub $4,%%esp ;"
+ " jmp 2f ;"
+ "1: btrl %%eax,%0 ;" /* clear bit */
+ " mov %%eax,(%%esp) ;"
+ " call do_IRQ ;" /* do_IRQ(event) */
+ "2: bsfl %0,%%eax ;" /* %eax == bit # */
+ " jnz 1b ;"
+ " add $8,%%esp ;"
+ /* we use %ebx because it is callee-saved */
+ : : "b" (events), "r" (regs)
+ /* clobbered by callback function calls */
+ : "eax", "ecx", "edx", "memory" );
+
+ /* Specialised local_irq_restore(). */
+ if ( flags ) set_bit(EVENTS_MASTER_ENABLE_BIT, &shared->events_mask);
+ barrier();
+ }
+ while ( shared->events );
+}
+
+
+
+/*
+ * Define interface to generic handling in irq.c
+ */
+
+static void shutdown_hypervisor_event(unsigned int irq)
+{
+ clear_bit(irq, &event_mask);
+ clear_bit(irq, &HYPERVISOR_shared_info->events_mask);
+}
+
+static void enable_hypervisor_event(unsigned int irq)
+{
+ set_bit(irq, &event_mask);
+ set_bit(irq, &HYPERVISOR_shared_info->events_mask);
+ if ( test_bit(EVENTS_MASTER_ENABLE_BIT,
+ &HYPERVISOR_shared_info->events_mask) )
+ do_hypervisor_callback(NULL);
+}
+
+static void disable_hypervisor_event(unsigned int irq)
+{
+ clear_bit(irq, &event_mask);
+ clear_bit(irq, &HYPERVISOR_shared_info->events_mask);
+}
+
+static void ack_hypervisor_event(unsigned int irq)
+{
+ if ( !(event_mask & (1<<irq)) )
+ {
+ printk("Unexpected hypervisor event %d\n", irq);
+ atomic_inc(&irq_err_count);
+ }
+ set_bit(irq, &HYPERVISOR_shared_info->events_mask);
+}
+
+static unsigned int startup_hypervisor_event(unsigned int irq)
+{
+ enable_hypervisor_event(irq);
+ return 0;
+}
+
+static void end_hypervisor_event(unsigned int irq)
+{
+}
+
+static struct hw_interrupt_type hypervisor_irq_type = {
+ "Hypervisor-event",
+ startup_hypervisor_event,
+ shutdown_hypervisor_event,
+ enable_hypervisor_event,
+ disable_hypervisor_event,
+ ack_hypervisor_event,
+ end_hypervisor_event,
+ NULL
+};
+
+void __init init_IRQ(void)
+{
+ int i;
+
+ for ( i = 0; i < NR_IRQS; i++ )
+ {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &hypervisor_irq_type;
+ }
+}