diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-03-25 11:51:43 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-03-25 11:51:43 +0000 |
commit | 163ce6261c54cbfe6fec6f011497a3d14d30b5e4 (patch) | |
tree | 00c39fb06d4bb8faf24d95fb4ce373757d382cd3 /xenolinux-2.4.25-sparse/include/asm-xen | |
parent | d6142516315665bd6d38c15e7ad826ed8d542f6b (diff) | |
download | xen-163ce6261c54cbfe6fec6f011497a3d14d30b5e4.tar.gz xen-163ce6261c54cbfe6fec6f011497a3d14d30b5e4.tar.bz2 xen-163ce6261c54cbfe6fec6f011497a3d14d30b5e4.zip |
bitkeeper revision 1.825.1.2 (4062c7cfNjG5kiKHfguNA2SIXnllng)
Many files:
New IRQ upcall world.
evtchn.c:
Rename: xenolinux-2.4.25-sparse/arch/xen/kernel/hypervisor.c -> xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c
Diffstat (limited to 'xenolinux-2.4.25-sparse/include/asm-xen')
-rw-r--r-- | xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h | 87 | ||||
-rw-r--r-- | xenolinux-2.4.25-sparse/include/asm-xen/hypervisor.h | 4 | ||||
-rw-r--r-- | xenolinux-2.4.25-sparse/include/asm-xen/irq.h | 27 | ||||
-rw-r--r-- | xenolinux-2.4.25-sparse/include/asm-xen/keyboard.h | 7 | ||||
-rw-r--r-- | xenolinux-2.4.25-sparse/include/asm-xen/system.h | 25 |
5 files changed, 119 insertions, 31 deletions
diff --git a/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h b/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h index 88c278d86e..2aea319dd5 100644 --- a/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h +++ b/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h @@ -1,7 +1,8 @@ /****************************************************************************** * evtchn.h * - * Driver for receiving and demuxing event-channel signals. + * Communication via Xen event channels. + * Also definitions for the device that demuxes notifications to userspace. * * Copyright (c) 2004, K A Fraser */ @@ -9,10 +10,81 @@ #ifndef __ASM_EVTCHN_H__ #define __ASM_EVTCHN_H__ -typedef void (*evtchn_receiver_t)(unsigned int); -#define PORT_NORMAL 0x0000 -#define PORT_DISCONNECT 0x8000 -#define PORTIDX_MASK 0x7fff +#include <linux/config.h> +#include <asm/hypervisor.h> +#include <asm/ptrace.h> + +/* + * LOW-LEVEL DEFINITIONS + */ + +/* Entry point for notifications into Linux subsystems. */ +void evtchn_do_upcall(struct pt_regs *regs); + +/* Entry point for notifications into the userland character device. */ +void evtchn_device_upcall(int port, int exception); + +static inline void mask_evtchn(int port) +{ + shared_info_t *s = HYPERVISOR_shared_info; + set_bit(port, &s->evtchn_mask[0]); +} + +/* + * I haven't thought too much about the synchronisation in here against + * other CPUs, but all the bit-update operations are reorder barriers on + * x86 so reordering concerns aren't a problem for now. Some mb() calls + * would be required on weaker architectures I think. -- KAF (24/3/2004) + */ +static inline void unmask_evtchn(int port) +{ + shared_info_t *s = HYPERVISOR_shared_info; + int need_upcall = 0; + + clear_bit(port, &s->evtchn_mask[0]); + + /* + * The following is basically the equivalent of 'hw_resend_irq'. Just like + * a real IO-APIC we 'lose the interrupt edge' if the channel is masked. + */ + + /* Asserted a standard notification? */ + if ( test_bit (port, &s->evtchn_pending[0]) && + !test_and_set_bit(port>>5, &s->evtchn_pending_sel) ) + need_upcall = 1; + + /* Asserted an exceptional notification? */ + if ( test_bit (port, &s->evtchn_exception[0]) && + !test_and_set_bit(port>>5, &s->evtchn_exception_sel) ) + need_upcall = 1; + + /* If asserted either type of notification, check the master flags. */ + if ( need_upcall && + !test_and_set_bit(0, &s->evtchn_upcall_pending) && + !test_bit (0, &s->evtchn_upcall_mask) ) + evtchn_do_upcall(NULL); +} + +static inline void clear_evtchn(int port) +{ + shared_info_t *s = HYPERVISOR_shared_info; + clear_bit(port, &s->evtchn_pending[0]); +} + +static inline void clear_evtchn_exception(int port) +{ + shared_info_t *s = HYPERVISOR_shared_info; + clear_bit(port, &s->evtchn_exception[0]); +} + + +/* + * CHARACTER-DEVICE DEFINITIONS + */ + +#define PORT_NORMAL 0x0000 +#define PORT_EXCEPTION 0x8000 +#define PORTIDX_MASK 0x7fff /* /dev/xen/evtchn resides at device number major=10, minor=200 */ #define EVTCHN_MINOR 200 @@ -21,9 +93,4 @@ typedef void (*evtchn_receiver_t)(unsigned int); /* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */ #define EVTCHN_RESET _IO('E', 1) -int evtchn_request_port(unsigned int port, evtchn_receiver_t rx_fn); -int evtchn_free_port(unsigned int port); -void evtchn_clear_port(unsigned int port); - - #endif /* __ASM_EVTCHN_H__ */ diff --git a/xenolinux-2.4.25-sparse/include/asm-xen/hypervisor.h b/xenolinux-2.4.25-sparse/include/asm-xen/hypervisor.h index 34d0974471..73149d5426 100644 --- a/xenolinux-2.4.25-sparse/include/asm-xen/hypervisor.h +++ b/xenolinux-2.4.25-sparse/include/asm-xen/hypervisor.h @@ -25,10 +25,6 @@ union start_info_union extern union start_info_union start_info_union; #define start_info (start_info_union.start_info) -/* arch/xen/kernel/hypervisor.c */ -void do_hypervisor_callback(struct pt_regs *regs); - - /* arch/xen/mm/hypervisor.c */ /* * NB. ptr values should be PHYSICAL, not MACHINE. 'vals' should be already 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 917a05334d..6d175ce6ab 100644 --- a/xenolinux-2.4.25-sparse/include/asm-xen/irq.h +++ b/xenolinux-2.4.25-sparse/include/asm-xen/irq.h @@ -14,19 +14,32 @@ #include <asm/hypervisor.h> #include <asm/ptrace.h> -#define NR_IRQS 256 +/* + * The flat IRQ space is divided into two regions: + * 1. A one-to-one mapping of real physical IRQs. This space is only used + * if we have physical device-access privilege. This region is at the + * start of the IRQ space so that existing device drivers do not need + * to be modified to translate physical IRQ numbers into our IRQ space. + * 3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These + * are bound using the provided bind/unbind functions. + */ -#define PHYS_IRQ_BASE 0 -#define NR_PHYS_IRQS 128 +#define PIRQ_BASE 0 +#define NR_PIRQS 128 -#define HYPEREVENT_IRQ_BASE 128 -#define NR_HYPEREVENT_IRQS 128 +#define DYNIRQ_BASE (PIRQ_BASE + NR_PIRQS) +#define NR_DYNIRQS 128 -#define HYPEREVENT_IRQ(_ev) ((_ev) + HYPEREVENT_IRQ_BASE) -#define HYPEREVENT_FROM_IRQ(_irq) ((_irq) - HYPEREVENT_IRQ_BASE) +#define NR_IRQS (NR_PIRQS + NR_DYNIRQS) extern void physirq_init(void); +/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */ +extern int bind_virq_to_irq(int virq); +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) extern void disable_irq(unsigned int); diff --git a/xenolinux-2.4.25-sparse/include/asm-xen/keyboard.h b/xenolinux-2.4.25-sparse/include/asm-xen/keyboard.h index 79d72da929..9066a3bada 100644 --- a/xenolinux-2.4.25-sparse/include/asm-xen/keyboard.h +++ b/xenolinux-2.4.25-sparse/include/asm-xen/keyboard.h @@ -58,8 +58,11 @@ static inline int xen_kbd_controller_present () /* resource allocation */ #define kbd_request_region() \ do { } while (0) -#define kbd_request_irq(handler) \ - request_irq(HYPEREVENT_IRQ(_EVENT_PS2), handler, 0, "ps/2", NULL) +#define kbd_request_irq(handler) \ + do { \ + int irq = bind_virq_to_irq(VIRQ_PS2); \ + request_irq(irq, handler, 0, "ps/2", NULL); \ + } while ( 0 ) /* could implement these with command to xen to filter mouse stuff... */ #define aux_request_irq(hand, dev_id) 0 diff --git a/xenolinux-2.4.25-sparse/include/asm-xen/system.h b/xenolinux-2.4.25-sparse/include/asm-xen/system.h index 3b59252ca3..2c1194a781 100644 --- a/xenolinux-2.4.25-sparse/include/asm-xen/system.h +++ b/xenolinux-2.4.25-sparse/include/asm-xen/system.h @@ -7,6 +7,7 @@ #include <asm/segment.h> #include <asm/hypervisor.h> #include <linux/bitops.h> /* for LOCK_PREFIX */ +#include <asm/evtchn.h> #ifdef __KERNEL__ @@ -319,29 +320,38 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, #define set_wmb(var, value) do { var = value; wmb(); } while (0) +/* + * NB. ALl the following routines are SMP-safe on x86, even where they look + * possibly racy. For example, we must ensure that we clear the mask bit and + * /then/ check teh pending bit. But this will happen because the bit-update + * operations are ordering barriers. + * + * For this reason also, many uses of 'barrier' here are rather anal. But + * they do no harm. + */ #define __cli() \ do { \ - clear_bit(EVENTS_MASTER_ENABLE_BIT, &HYPERVISOR_shared_info->events_mask);\ + set_bit(0, &HYPERVISOR_shared_info->evtchn_upcall_mask); \ barrier(); \ } while (0) #define __sti() \ do { \ shared_info_t *_shared = HYPERVISOR_shared_info; \ - set_bit(EVENTS_MASTER_ENABLE_BIT, &_shared->events_mask); \ + clear_bit(0, &_shared->evtchn_upcall_mask); \ barrier(); \ - if ( unlikely(_shared->events) ) do_hypervisor_callback(NULL); \ + if ( unlikely(test_bit(0, &_shared->evtchn_upcall_pending)) ) \ + evtchn_do_upcall(NULL); \ } while (0) #define __save_flags(x) \ do { \ - (x) = test_bit(EVENTS_MASTER_ENABLE_BIT, \ - &HYPERVISOR_shared_info->events_mask); \ + (x) = test_bit(0, &HYPERVISOR_shared_info->evtchn_upcall_mask); \ barrier(); \ } while (0) -#define __restore_flags(x) do { if (x) __sti(); } while (0) +#define __restore_flags(x) do { if (x) __cli(); else __sti(); } while (0) #define safe_halt() ((void)0) @@ -350,8 +360,7 @@ do { \ #define local_irq_save(x) \ do { \ - (x) = test_and_clear_bit(EVENTS_MASTER_ENABLE_BIT, \ - &HYPERVISOR_shared_info->events_mask); \ + (x) = test_and_set_bit(0, &HYPERVISOR_shared_info->evtchn_upcall_mask); \ barrier(); \ } while (0) #define local_irq_restore(x) __restore_flags(x) |