ia64/xen-unstable

changeset 2445:60e68411ab8a

bitkeeper revision 1.1159.72.3 (413cb565kAu26gtMpvumani1Zx6Vjw)

Add new files in NetBSD for Xen2.0.
author cl349@labyrinth.cl.cam.ac.uk
date Mon Sep 06 19:07:17 2004 +0000 (2004-09-06)
parents 7432c2c8b98b
children 309c1fb27f87
files .rootkeys netbsd-2.0-xen-sparse/sys/arch/xen/include/ctrl_if.h netbsd-2.0-xen-sparse/sys/arch/xen/include/evtchn.h netbsd-2.0-xen-sparse/sys/arch/xen/xen/ctrl_if.c netbsd-2.0-xen-sparse/sys/arch/xen/xen/evtchn.c
line diff
     1.1 --- a/.rootkeys	Mon Sep 06 19:04:16 2004 +0000
     1.2 +++ b/.rootkeys	Mon Sep 06 19:07:17 2004 +0000
     1.3 @@ -274,6 +274,8 @@ 413cb3b4bvVJ7UlliMSH60J4uIb9kA netbsd-2.
     1.4  413cb3b4aKd9SUY-OzUiTF0Gb9ve9w netbsd-2.0-xen-sparse/sys/arch/xen/i386/sys_machdep.c
     1.5  413cb3b4jUtWl-sP493PvB27o-Iltw netbsd-2.0-xen-sparse/sys/arch/xen/i386/vector.S
     1.6  413cb3b4ElwwoJEmmzflV0HgK5Qxcg netbsd-2.0-xen-sparse/sys/arch/xen/i386/xen_machdep.c
     1.7 +413cb564XpMxewOF9BCK37BNcDewHQ netbsd-2.0-xen-sparse/sys/arch/xen/include/ctrl_if.h
     1.8 +413cb564rB0n4HPqzYQxBvfR9r-KeQ netbsd-2.0-xen-sparse/sys/arch/xen/include/evtchn.h
     1.9  413cb3b4k9OVRCxuSdhKt-2baTp_Yg netbsd-2.0-xen-sparse/sys/arch/xen/include/frameasm.h
    1.10  413cb3b4bRsqiHQLTKEZk4-zOksf8A netbsd-2.0-xen-sparse/sys/arch/xen/include/hypervisor.h
    1.11  413cb3b4OqY83qI8GztIZGADpvrpSw netbsd-2.0-xen-sparse/sys/arch/xen/include/if_xennetvar.h
    1.12 @@ -283,6 +285,8 @@ 413cb3b4ullQud70n4JClwoEEUBh8Q netbsd-2.
    1.13  413cb3b4y1Ffq8BOhbdSpn-fGmKuEg netbsd-2.0-xen-sparse/sys/arch/xen/include/xenpmap.h
    1.14  413cb3b4uXOFcT56QuLt1fcDrB-4Zg netbsd-2.0-xen-sparse/sys/arch/xen/x86/bus_space.c
    1.15  413cb3b4hIffjrKn3zhVqJmH6ueB3Q netbsd-2.0-xen-sparse/sys/arch/xen/xen/clock.c
    1.16 +413cb564SakPue2EEm4MTtRb4z5JVw netbsd-2.0-xen-sparse/sys/arch/xen/xen/ctrl_if.c
    1.17 +413cb564uNQuIozl7hperSVK9EeDCA netbsd-2.0-xen-sparse/sys/arch/xen/xen/evtchn.c
    1.18  413cb3b4eNdRIasCoQIuX4Nu39Dlqw netbsd-2.0-xen-sparse/sys/arch/xen/xen/hypervisor.c
    1.19  413cb3b40DLJLbX_ZUIULB0JFjBuaw netbsd-2.0-xen-sparse/sys/arch/xen/xen/if_xennet.c
    1.20  413cb3b46JnvK1UurZAubeQoFg1W-w netbsd-2.0-xen-sparse/sys/arch/xen/xen/xbd.c
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/include/ctrl_if.h	Mon Sep 06 19:07:17 2004 +0000
     2.3 @@ -0,0 +1,138 @@
     2.4 +/******************************************************************************
     2.5 + * ctrl_if.h
     2.6 + * 
     2.7 + * Management functions for special interface to the domain controller.
     2.8 + * 
     2.9 + * Copyright (c) 2004, K A Fraser
    2.10 + */
    2.11 +
    2.12 +#ifndef __ASM_XEN__CTRL_IF_H__
    2.13 +#define __ASM_XEN__CTRL_IF_H__
    2.14 +
    2.15 +typedef control_msg_t ctrl_msg_t;
    2.16 +
    2.17 +/*
    2.18 + * Callback function type. Called for asynchronous processing of received
    2.19 + * request messages, and responses to previously-transmitted request messages.
    2.20 + * The parameters are (@msg, @id).
    2.21 + *  @msg: Original request/response message (not a copy). The message can be
    2.22 + *        modified in-place by the handler (e.g., a response callback can
    2.23 + *        turn a request message into a response message in place). The message
    2.24 + *        is no longer accessible after the callback handler returns -- if the
    2.25 + *        message is required to persist for longer then it must be copied.
    2.26 + *  @id:  (Response callbacks only) The 'id' that was specified when the
    2.27 + *        original request message was queued for transmission.
    2.28 + */
    2.29 +typedef void (*ctrl_msg_handler_t)(ctrl_msg_t *, unsigned long);
    2.30 +
    2.31 +/*
    2.32 + * Send @msg to the domain controller. Execute @hnd when a response is
    2.33 + * received, passing the response message and the specified @id. This
    2.34 + * operation will not block: it will return -EAGAIN if there is no space.
    2.35 + * Notes:
    2.36 + *  1. The @msg is copied if it is transmitted and so can be freed after this
    2.37 + *     function returns.
    2.38 + *  2. If @hnd is NULL then no callback is executed.
    2.39 + */
    2.40 +int
    2.41 +ctrl_if_send_message_noblock(
    2.42 +    ctrl_msg_t *msg, 
    2.43 +    ctrl_msg_handler_t hnd,
    2.44 +    unsigned long id);
    2.45 +
    2.46 +/*
    2.47 + * Send @msg to the domain controller. Execute @hnd when a response is
    2.48 + * received, passing the response message and the specified @id. This
    2.49 + * operation will block until the message is sent, or a signal is received
    2.50 + * for the calling process (unless @wait_state is TASK_UNINTERRUPTIBLE).
    2.51 + * Notes:
    2.52 + *  1. The @msg is copied if it is transmitted and so can be freed after this
    2.53 + *     function returns.
    2.54 + *  2. If @hnd is NULL then no callback is executed.
    2.55 + */
    2.56 +int
    2.57 +ctrl_if_send_message_block(
    2.58 +    ctrl_msg_t *msg, 
    2.59 +    ctrl_msg_handler_t hnd, 
    2.60 +    unsigned long id, 
    2.61 +    long wait_state);
    2.62 +
    2.63 +/*
    2.64 + * Send @msg to the domain controller. Block until the response is received,
    2.65 + * and then copy it into the provided buffer, @rmsg.
    2.66 + */
    2.67 +int
    2.68 +ctrl_if_send_message_and_get_response(
    2.69 +    ctrl_msg_t *msg,
    2.70 +    ctrl_msg_t *rmsg,
    2.71 +    long wait_state);
    2.72 +
    2.73 +#ifdef notyet
    2.74 +/*
    2.75 + * Request a callback when there is /possibly/ space to immediately send a
    2.76 + * message to the domain controller. This function returns 0 if there is
    2.77 + * already space to trasnmit a message --- in this case the callback task /may/
    2.78 + * still be executed. If this function returns 1 then the callback /will/ be
    2.79 + * executed when space becomes available.
    2.80 + */
    2.81 +int
    2.82 +ctrl_if_enqueue_space_callback(
    2.83 +    struct tq_struct *task);
    2.84 +#endif
    2.85 +
    2.86 +/*
    2.87 + * Send a response (@msg) to a message from the domain controller. This will 
    2.88 + * never block.
    2.89 + * Notes:
    2.90 + *  1. The @msg is copied and so can be freed after this function returns.
    2.91 + *  2. The @msg may be the original request message, modified in-place.
    2.92 + */
    2.93 +void
    2.94 +ctrl_if_send_response(
    2.95 +    ctrl_msg_t *msg);
    2.96 +
    2.97 +/*
    2.98 + * Register a receiver for typed messages from the domain controller. The 
    2.99 + * handler (@hnd) is called for every received message of specified @type.
   2.100 + * Returns TRUE (non-zero) if the handler was successfully registered.
   2.101 + * If CALLBACK_IN_BLOCKING CONTEXT is specified in @flags then callbacks will
   2.102 + * occur in a context in which it is safe to yield (i.e., process context).
   2.103 + */
   2.104 +#define CALLBACK_IN_BLOCKING_CONTEXT 1
   2.105 +int ctrl_if_register_receiver(
   2.106 +    uint8_t type, 
   2.107 +    ctrl_msg_handler_t hnd,
   2.108 +    unsigned int flags);
   2.109 +
   2.110 +/*
   2.111 + * Unregister a receiver for typed messages from the domain controller. The 
   2.112 + * handler (@hnd) will not be executed after this function returns.
   2.113 + */
   2.114 +void
   2.115 +ctrl_if_unregister_receiver(
   2.116 +    uint8_t type, ctrl_msg_handler_t hnd);
   2.117 +
   2.118 +/* Suspend/resume notifications. */
   2.119 +void ctrl_if_suspend(void);
   2.120 +void ctrl_if_resume(void);
   2.121 +
   2.122 +/* Start-of-day setup. */
   2.123 +void ctrl_if_init(void);
   2.124 +
   2.125 +/*
   2.126 + * Returns TRUE if there are no outstanding message requests at the domain
   2.127 + * controller. This can be used to ensure that messages have really flushed
   2.128 + * through when it is not possible to use the response-callback interface.
   2.129 + * WARNING: If other subsystems are using the control interface then this
   2.130 + * function might never return TRUE!
   2.131 + */
   2.132 +int ctrl_if_transmitter_empty(void);  /* !! DANGEROUS FUNCTION !! */
   2.133 +
   2.134 +/*
   2.135 + * Manually discard response messages from the domain controller. 
   2.136 + * WARNING: This is usually done automatically -- this function should only
   2.137 + * be called when normal interrupt mechanisms are disabled!
   2.138 + */
   2.139 +void ctrl_if_discard_responses(void); /* !! DANGEROUS FUNCTION !! */
   2.140 +
   2.141 +#endif /* __ASM_XEN__CONTROL_IF_H__ */
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/include/evtchn.h	Mon Sep 06 19:07:17 2004 +0000
     3.3 @@ -0,0 +1,53 @@
     3.4 +/*	$NetBSD$	*/
     3.5 +
     3.6 +/*
     3.7 + *
     3.8 + * Copyright (c) 2004 Christian Limpach.
     3.9 + * All rights reserved.
    3.10 + *
    3.11 + * Redistribution and use in source and binary forms, with or without
    3.12 + * modification, are permitted provided that the following conditions
    3.13 + * are met:
    3.14 + * 1. Redistributions of source code must retain the above copyright
    3.15 + *    notice, this list of conditions and the following disclaimer.
    3.16 + * 2. Redistributions in binary form must reproduce the above copyright
    3.17 + *    notice, this list of conditions and the following disclaimer in the
    3.18 + *    documentation and/or other materials provided with the distribution.
    3.19 + * 3. All advertising materials mentioning features or use of this software
    3.20 + *    must display the following acknowledgement:
    3.21 + *      This product includes software developed by Christian Limpach.
    3.22 + * 4. The name of the author may not be used to endorse or promote products
    3.23 + *    derived from this software without specific prior written permission.
    3.24 + *
    3.25 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    3.26 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    3.27 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    3.28 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    3.29 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    3.30 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    3.31 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    3.32 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    3.33 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    3.34 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    3.35 + */
    3.36 +
    3.37 +#ifndef _XEN_EVENTS_H_
    3.38 +#define _XEN_EVENTS_H_
    3.39 +
    3.40 +#define	NR_IRQS		32
    3.41 +
    3.42 +extern int evtchn_to_irq[];
    3.43 +
    3.44 +/* typedef unsigned int (*ev_handler_t)(int, struct pt_regs *); */
    3.45 +typedef int (*ev_handler_t)(void *);
    3.46 +
    3.47 +void events_default_setup(void);
    3.48 +void init_events(void);
    3.49 +unsigned int do_event(int, struct trapframe *);
    3.50 +int event_set_handler(int, ev_handler_t, void *, int);
    3.51 +
    3.52 +int bind_virq_to_irq(int);
    3.53 +void unbind_virq_from_irq(int);
    3.54 +int bind_evtchn_to_irq(int);
    3.55 +
    3.56 +#endif /*  _XEN_EVENTS_H_ */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/xen/ctrl_if.c	Mon Sep 06 19:07:17 2004 +0000
     4.3 @@ -0,0 +1,573 @@
     4.4 +/******************************************************************************
     4.5 + * ctrl_if.c
     4.6 + * 
     4.7 + * Management functions for special interface to the domain controller.
     4.8 + * 
     4.9 + * Copyright (c) 2004, K A Fraser
    4.10 + */
    4.11 +
    4.12 +#include <sys/cdefs.h>
    4.13 +__KERNEL_RCSID(0, "$NetBSD$");
    4.14 +
    4.15 +#include <sys/param.h>
    4.16 +#include <sys/systm.h>
    4.17 +#include <sys/proc.h>
    4.18 +#include <sys/malloc.h>
    4.19 +#include <sys/kthread.h>
    4.20 +
    4.21 +#include <machine/xen.h>
    4.22 +#include <machine/hypervisor.h>
    4.23 +#include <machine/ctrl_if.h>
    4.24 +#include <machine/evtchn.h>
    4.25 +
    4.26 +#if 0
    4.27 +#define DPRINTK(_f, _a...) printf("(file=%s, line=%d) " _f, \
    4.28 +                           __FILE__ , __LINE__ , ## _a )
    4.29 +#else
    4.30 +#define DPRINTK(_f, _a...) ((void)0)
    4.31 +#endif
    4.32 +
    4.33 +/*
    4.34 + * Only used by initial domain which must create its own control-interface
    4.35 + * event channel. This value is picked up by the user-space domain controller
    4.36 + * via an ioctl.
    4.37 + */
    4.38 +int initdom_ctrlif_domcontroller_port = -1;
    4.39 +
    4.40 +static int ctrl_if_evtchn;
    4.41 +static int ctrl_if_irq;
    4.42 +static struct simplelock ctrl_if_lock;
    4.43 +
    4.44 +static CONTROL_RING_IDX ctrl_if_tx_resp_cons;
    4.45 +static CONTROL_RING_IDX ctrl_if_rx_req_cons;
    4.46 +
    4.47 +/* Incoming message requests. */
    4.48 +    /* Primary message type -> message handler. */
    4.49 +static ctrl_msg_handler_t ctrl_if_rxmsg_handler[256];
    4.50 +    /* Primary message type -> callback in process context? */
    4.51 +static unsigned long ctrl_if_rxmsg_blocking_context[256/sizeof(unsigned long)];
    4.52 +#if 0
    4.53 +    /* Is it late enough during bootstrap to use schedule_task()? */
    4.54 +static int safe_to_schedule_task;
    4.55 +#endif
    4.56 +    /* Queue up messages to be handled in process context. */
    4.57 +static ctrl_msg_t ctrl_if_rxmsg_deferred[CONTROL_RING_SIZE];
    4.58 +static CONTROL_RING_IDX ctrl_if_rxmsg_deferred_prod;
    4.59 +static CONTROL_RING_IDX ctrl_if_rxmsg_deferred_cons;
    4.60 +
    4.61 +/* Incoming message responses: message identifier -> message handler/id. */
    4.62 +static struct {
    4.63 +    ctrl_msg_handler_t fn;
    4.64 +    unsigned long      id;
    4.65 +} ctrl_if_txmsg_id_mapping[CONTROL_RING_SIZE];
    4.66 +
    4.67 +/* For received messages that must be deferred to process context. */
    4.68 +static void __ctrl_if_rxmsg_deferred(void *unused);
    4.69 +
    4.70 +#ifdef notyet
    4.71 +/* Deferred callbacks for people waiting for space in the transmit ring. */
    4.72 +static int DECLARE_TASK_QUEUE(ctrl_if_tx_tq);
    4.73 +#endif
    4.74 +
    4.75 +static void *ctrl_if_softintr = NULL;
    4.76 +
    4.77 +static int ctrl_if_tx_wait;
    4.78 +static void __ctrl_if_tx_tasklet(unsigned long data);
    4.79 +
    4.80 +static void __ctrl_if_rx_tasklet(unsigned long data);
    4.81 +
    4.82 +static void ctrl_if_kthread(void *);
    4.83 +
    4.84 +#define get_ctrl_if() ((control_if_t *)((char *)HYPERVISOR_shared_info + 2048))
    4.85 +#define TX_FULL(_c)   \
    4.86 +    (((_c)->tx_req_prod - ctrl_if_tx_resp_cons) == CONTROL_RING_SIZE)
    4.87 +
    4.88 +static void ctrl_if_notify_controller(void)
    4.89 +{
    4.90 +    hypervisor_notify_via_evtchn(ctrl_if_evtchn);
    4.91 +}
    4.92 +
    4.93 +static void ctrl_if_rxmsg_default_handler(ctrl_msg_t *msg, unsigned long id)
    4.94 +{
    4.95 +    msg->length = 0;
    4.96 +    ctrl_if_send_response(msg);
    4.97 +}
    4.98 +
    4.99 +static void __ctrl_if_tx_tasklet(unsigned long data)
   4.100 +{
   4.101 +    control_if_t *ctrl_if = get_ctrl_if();
   4.102 +    ctrl_msg_t   *msg;
   4.103 +    int           was_full = TX_FULL(ctrl_if);
   4.104 +    CONTROL_RING_IDX rp;
   4.105 +
   4.106 +    rp = ctrl_if->tx_resp_prod;
   4.107 +    __insn_barrier(); /* Ensure we see all requests up to 'rp'. */
   4.108 +
   4.109 +    while ( ctrl_if_tx_resp_cons != rp )
   4.110 +    {
   4.111 +        msg = &ctrl_if->tx_ring[MASK_CONTROL_IDX(ctrl_if_tx_resp_cons)];
   4.112 +
   4.113 +        DPRINTK("Rx-Rsp %u/%u :: %d/%d\n", 
   4.114 +                ctrl_if_tx_resp_cons,
   4.115 +                ctrl_if->tx_resp_prod,
   4.116 +                msg->type, msg->subtype);
   4.117 +
   4.118 +        /* Execute the callback handler, if one was specified. */
   4.119 +        if ( msg->id != 0xFF )
   4.120 +        {
   4.121 +            (*ctrl_if_txmsg_id_mapping[msg->id].fn)(
   4.122 +                msg, ctrl_if_txmsg_id_mapping[msg->id].id);
   4.123 +            __insn_barrier(); /* Execute, /then/ free. */
   4.124 +            ctrl_if_txmsg_id_mapping[msg->id].fn = NULL;
   4.125 +        }
   4.126 +
   4.127 +        /*
   4.128 +         * Step over the message in the ring /after/ finishing reading it. As 
   4.129 +         * soon as the index is updated then the message may get blown away.
   4.130 +         */
   4.131 +        __insn_barrier();
   4.132 +        ctrl_if_tx_resp_cons++;
   4.133 +    }
   4.134 +
   4.135 +    if ( was_full && !TX_FULL(ctrl_if) )
   4.136 +    {
   4.137 +        wakeup(&ctrl_if_tx_wait);
   4.138 +#ifdef notyet
   4.139 +        run_task_queue(&ctrl_if_tx_tq);
   4.140 +#endif
   4.141 +    }
   4.142 +}
   4.143 +
   4.144 +static void __ctrl_if_rxmsg_deferred(void *unused)
   4.145 +{
   4.146 +	ctrl_msg_t *msg;
   4.147 +	CONTROL_RING_IDX dp;
   4.148 +
   4.149 +	dp = ctrl_if_rxmsg_deferred_prod;
   4.150 +	__insn_barrier(); /* Ensure we see all deferred requests up to 'dp'. */
   4.151 +
   4.152 +	while ( ctrl_if_rxmsg_deferred_cons != dp )
   4.153 +	{
   4.154 +		msg = &ctrl_if_rxmsg_deferred[MASK_CONTROL_IDX(
   4.155 +						      ctrl_if_rxmsg_deferred_cons++)];
   4.156 +		(*ctrl_if_rxmsg_handler[msg->type])(msg, 0);
   4.157 +	}
   4.158 +}
   4.159 +
   4.160 +static void __ctrl_if_rx_tasklet(unsigned long data)
   4.161 +{
   4.162 +    control_if_t *ctrl_if = get_ctrl_if();
   4.163 +    ctrl_msg_t    msg, *pmsg;
   4.164 +    CONTROL_RING_IDX rp, dp;
   4.165 +
   4.166 +    dp = ctrl_if_rxmsg_deferred_prod;
   4.167 +    rp = ctrl_if->rx_req_prod;
   4.168 +    __insn_barrier(); /* Ensure we see all requests up to 'rp'. */
   4.169 +
   4.170 +    while ( ctrl_if_rx_req_cons != rp )
   4.171 +    {
   4.172 +        pmsg = &ctrl_if->rx_ring[MASK_CONTROL_IDX(ctrl_if_rx_req_cons++)];
   4.173 +        memcpy(&msg, pmsg, offsetof(ctrl_msg_t, msg));
   4.174 +
   4.175 +        DPRINTK("Rx-Req %u/%u :: %d/%d\n", 
   4.176 +                ctrl_if_rx_req_cons-1,
   4.177 +                ctrl_if->rx_req_prod,
   4.178 +                msg.type, msg.subtype);
   4.179 +
   4.180 +        if ( msg.length != 0 )
   4.181 +            memcpy(msg.msg, pmsg->msg, msg.length);
   4.182 +
   4.183 +        if ( x86_atomic_test_bit(
   4.184 +                      (unsigned long *)&ctrl_if_rxmsg_blocking_context,
   4.185 +		      msg.type) )
   4.186 +            memcpy(&ctrl_if_rxmsg_deferred[MASK_CONTROL_IDX(dp++)],
   4.187 +                   &msg, offsetof(ctrl_msg_t, msg) + msg.length);
   4.188 +        else
   4.189 +            (*ctrl_if_rxmsg_handler[msg.type])(&msg, 0);
   4.190 +    }
   4.191 +
   4.192 +    if ( dp != ctrl_if_rxmsg_deferred_prod )
   4.193 +    {
   4.194 +        __insn_barrier();
   4.195 +        ctrl_if_rxmsg_deferred_prod = dp;
   4.196 +#if 0
   4.197 +        wakeup(&ctrl_if_kthread);
   4.198 +#else
   4.199 +	if (ctrl_if_softintr)
   4.200 +		softintr_schedule(ctrl_if_softintr);
   4.201 +#endif
   4.202 +    }
   4.203 +}
   4.204 +
   4.205 +static int ctrl_if_interrupt(void *arg)
   4.206 +{
   4.207 +    control_if_t *ctrl_if = get_ctrl_if();
   4.208 +
   4.209 +    if ( ctrl_if_tx_resp_cons != ctrl_if->tx_resp_prod ||
   4.210 +	ctrl_if_rx_req_cons != ctrl_if->rx_req_prod ) {
   4.211 +#if 0
   4.212 +	    wakeup(&ctrl_if_kthread);
   4.213 +#else
   4.214 +	    if (ctrl_if_softintr)
   4.215 +		    softintr_schedule(ctrl_if_softintr);
   4.216 +#endif
   4.217 +    }
   4.218 +
   4.219 +    return 0;
   4.220 +}
   4.221 +
   4.222 +int
   4.223 +ctrl_if_send_message_noblock(
   4.224 +    ctrl_msg_t *msg, 
   4.225 +    ctrl_msg_handler_t hnd,
   4.226 +    unsigned long id)
   4.227 +{
   4.228 +    control_if_t *ctrl_if = get_ctrl_if();
   4.229 +    unsigned long flags;
   4.230 +    int           i;
   4.231 +
   4.232 +    save_and_cli(flags);
   4.233 +    simple_lock(&ctrl_if_lock);
   4.234 +
   4.235 +    if ( TX_FULL(ctrl_if) )
   4.236 +    {
   4.237 +        simple_unlock(&ctrl_if_lock);
   4.238 +	restore_flags(flags);
   4.239 +        return -EAGAIN;
   4.240 +    }
   4.241 +
   4.242 +    msg->id = 0xFF;
   4.243 +    if ( hnd != NULL )
   4.244 +    {
   4.245 +        for ( i = 0; ctrl_if_txmsg_id_mapping[i].fn != NULL; i++ )
   4.246 +            continue;
   4.247 +        ctrl_if_txmsg_id_mapping[i].fn = hnd;
   4.248 +        ctrl_if_txmsg_id_mapping[i].id = id;
   4.249 +        msg->id = i;
   4.250 +    }
   4.251 +
   4.252 +    DPRINTK("Tx-Req %u/%u :: %d/%d\n", 
   4.253 +            ctrl_if->tx_req_prod, 
   4.254 +            ctrl_if_tx_resp_cons,
   4.255 +            msg->type, msg->subtype);
   4.256 +
   4.257 +    memcpy(&ctrl_if->tx_ring[MASK_CONTROL_IDX(ctrl_if->tx_req_prod)], 
   4.258 +           msg, sizeof(*msg));
   4.259 +    __insn_barrier(); /* Write the message before letting the controller peek at it. */
   4.260 +    ctrl_if->tx_req_prod++;
   4.261 +
   4.262 +    simple_unlock(&ctrl_if_lock);
   4.263 +    restore_flags(flags);
   4.264 +
   4.265 +    ctrl_if_notify_controller();
   4.266 +
   4.267 +    return 0;
   4.268 +}
   4.269 +
   4.270 +int
   4.271 +ctrl_if_send_message_block(
   4.272 +    ctrl_msg_t *msg, 
   4.273 +    ctrl_msg_handler_t hnd, 
   4.274 +    unsigned long id,
   4.275 +    long wait_state)
   4.276 +{
   4.277 +	int rc;
   4.278 +
   4.279 +	while ((rc = ctrl_if_send_message_noblock(msg, hnd, id)) == EAGAIN) {
   4.280 +		/* XXXcl possible race -> add a lock and ltsleep */
   4.281 +		rc = tsleep((caddr_t) &ctrl_if_tx_wait, PUSER | PCATCH,
   4.282 +		    "ctrl_if", 0);
   4.283 +		if (rc)
   4.284 +			break;
   4.285 +	}
   4.286 +
   4.287 +	return rc;
   4.288 +}
   4.289 +
   4.290 +/* Allow a reponse-callback handler to find context of a blocked requester.  */
   4.291 +struct rsp_wait {
   4.292 +    ctrl_msg_t         *msg;  /* Buffer for the response message.            */
   4.293 +    struct task_struct *task; /* The task that is blocked on the response.   */
   4.294 +    int                 done; /* Indicate to 'task' that response is rcv'ed. */
   4.295 +};
   4.296 +
   4.297 +static void __ctrl_if_get_response(ctrl_msg_t *msg, unsigned long id)
   4.298 +{
   4.299 +    struct rsp_wait    *wait = (struct rsp_wait *)id;
   4.300 +
   4.301 +    memcpy(wait->msg, msg, sizeof(*msg));
   4.302 +    __insn_barrier();
   4.303 +    wait->done = 1;
   4.304 +
   4.305 +    wakeup(wait);
   4.306 +}
   4.307 +
   4.308 +int
   4.309 +ctrl_if_send_message_and_get_response(
   4.310 +    ctrl_msg_t *msg, 
   4.311 +    ctrl_msg_t *rmsg,
   4.312 +    long wait_state)
   4.313 +{
   4.314 +    struct rsp_wait wait;
   4.315 +    int rc;
   4.316 +
   4.317 +    wait.msg  = rmsg;
   4.318 +    wait.done = 0;
   4.319 +
   4.320 +    if ( (rc = ctrl_if_send_message_block(msg, __ctrl_if_get_response,
   4.321 +                                          (unsigned long)&wait,
   4.322 +                                          wait_state)) != 0 )
   4.323 +        return rc;
   4.324 +
   4.325 +    for ( ; ; )
   4.326 +    {
   4.327 +	    if ( wait.done )
   4.328 +		    break;
   4.329 +	    tsleep((caddr_t)&wait, PUSER | PCATCH, "ctrl_if", 0);
   4.330 +    }
   4.331 +
   4.332 +    return 0;
   4.333 +}
   4.334 +
   4.335 +#ifdef notyet
   4.336 +int
   4.337 +ctrl_if_enqueue_space_callback(
   4.338 +    struct tq_struct *task)
   4.339 +{
   4.340 +    control_if_t *ctrl_if = get_ctrl_if();
   4.341 +
   4.342 +    /* Fast path. */
   4.343 +    if ( !TX_FULL(ctrl_if) )
   4.344 +        return 0;
   4.345 +
   4.346 +    (void)queue_task(task, &ctrl_if_tx_tq);
   4.347 +
   4.348 +    /*
   4.349 +     * We may race execution of the task queue, so return re-checked status. If
   4.350 +     * the task is not executed despite the ring being non-full then we will
   4.351 +     * certainly return 'not full'.
   4.352 +     */
   4.353 +    __insn_barrier();
   4.354 +    return TX_FULL(ctrl_if);
   4.355 +}
   4.356 +#endif
   4.357 +
   4.358 +void
   4.359 +ctrl_if_send_response(
   4.360 +    ctrl_msg_t *msg)
   4.361 +{
   4.362 +    control_if_t *ctrl_if = get_ctrl_if();
   4.363 +    unsigned long flags;
   4.364 +    ctrl_msg_t   *dmsg;
   4.365 +
   4.366 +    /*
   4.367 +     * NB. The response may the original request message, modified in-place.
   4.368 +     * In this situation we may have src==dst, so no copying is required.
   4.369 +     */
   4.370 +    save_and_cli(flags);
   4.371 +    simple_lock(&ctrl_if_lock);
   4.372 +
   4.373 +    DPRINTK("Tx-Rsp %u :: %d/%d\n", 
   4.374 +            ctrl_if->rx_resp_prod, 
   4.375 +            msg->type, msg->subtype);
   4.376 +
   4.377 +    dmsg = &ctrl_if->rx_ring[MASK_CONTROL_IDX(ctrl_if->rx_resp_prod)];
   4.378 +    if ( dmsg != msg )
   4.379 +        memcpy(dmsg, msg, sizeof(*msg));
   4.380 +
   4.381 +    __insn_barrier(); /* Write the message before letting the controller peek at it. */
   4.382 +    ctrl_if->rx_resp_prod++;
   4.383 +
   4.384 +    simple_unlock(&ctrl_if_lock);
   4.385 +    restore_flags(flags);
   4.386 +
   4.387 +    ctrl_if_notify_controller();
   4.388 +}
   4.389 +
   4.390 +int
   4.391 +ctrl_if_register_receiver(
   4.392 +    uint8_t type, 
   4.393 +    ctrl_msg_handler_t hnd, 
   4.394 +    unsigned int flags)
   4.395 +{
   4.396 +    unsigned long _flags;
   4.397 +    int inuse;
   4.398 +
   4.399 +    save_and_cli(_flags);
   4.400 +    simple_lock(&ctrl_if_lock);
   4.401 +
   4.402 +    inuse = (ctrl_if_rxmsg_handler[type] != ctrl_if_rxmsg_default_handler);
   4.403 +
   4.404 +    if ( inuse )
   4.405 +    {
   4.406 +        printf("Receiver %p already established for control "
   4.407 +               "messages of type %d.\n", ctrl_if_rxmsg_handler[type], type);
   4.408 +    }
   4.409 +    else
   4.410 +    {
   4.411 +        ctrl_if_rxmsg_handler[type] = hnd;
   4.412 +        x86_atomic_clear_bit((unsigned long *)&ctrl_if_rxmsg_blocking_context, type);
   4.413 +        if ( flags == CALLBACK_IN_BLOCKING_CONTEXT )
   4.414 +        {
   4.415 +            x86_atomic_set_bit((unsigned long *)&ctrl_if_rxmsg_blocking_context, type);
   4.416 +#if 0
   4.417 +            if ( !safe_to_schedule_task )
   4.418 +                BUG();
   4.419 +#endif
   4.420 +        }
   4.421 +    }
   4.422 +
   4.423 +    simple_unlock(&ctrl_if_lock);
   4.424 +    restore_flags(_flags);
   4.425 +
   4.426 +    return !inuse;
   4.427 +}
   4.428 +
   4.429 +void 
   4.430 +ctrl_if_unregister_receiver(
   4.431 +    uint8_t type,
   4.432 +    ctrl_msg_handler_t hnd)
   4.433 +{
   4.434 +    unsigned long flags;
   4.435 +
   4.436 +    save_and_cli(flags);
   4.437 +    simple_lock(&ctrl_if_lock);
   4.438 +
   4.439 +    if ( ctrl_if_rxmsg_handler[type] != hnd )
   4.440 +        printf("Receiver %p is not registered for control "
   4.441 +               "messages of type %d.\n", hnd, type);
   4.442 +    else
   4.443 +        ctrl_if_rxmsg_handler[type] = ctrl_if_rxmsg_default_handler;
   4.444 +
   4.445 +    simple_unlock(&ctrl_if_lock);
   4.446 +    restore_flags(flags);
   4.447 +
   4.448 +    /* Ensure that @hnd will not be executed after this function returns. */
   4.449 +#if 0
   4.450 +    wakeup(&ctrl_if_kthread);
   4.451 +#else
   4.452 +    if (ctrl_if_softintr)
   4.453 +	    softintr_schedule(ctrl_if_softintr);
   4.454 +#endif
   4.455 +}
   4.456 +
   4.457 +static void
   4.458 +ctrl_if_kthread(void *arg)
   4.459 +{
   4.460 +	control_if_t *ctrl_if = get_ctrl_if();
   4.461 +
   4.462 +	// printf("ctrl_if_kthread starting\n");
   4.463 +	for (;;) {
   4.464 +		if ( ctrl_if_tx_resp_cons != ctrl_if->tx_resp_prod )
   4.465 +			__ctrl_if_tx_tasklet(0);
   4.466 +
   4.467 +		if ( ctrl_if_rx_req_cons != ctrl_if->rx_req_prod )
   4.468 +			__ctrl_if_rx_tasklet(0);
   4.469 +
   4.470 +		if ( ctrl_if_rxmsg_deferred_cons !=
   4.471 +		    ctrl_if_rxmsg_deferred_prod )
   4.472 +			__ctrl_if_rxmsg_deferred(NULL);
   4.473 +
   4.474 +		if (arg) {
   4.475 +			// printf("ctrl_if_kthread one-shot done\n");
   4.476 +			return;
   4.477 +		}
   4.478 +
   4.479 +		tsleep((caddr_t)&ctrl_if_kthread, PUSER | PCATCH,
   4.480 +		    "ctrl_if", 0);
   4.481 +	}
   4.482 +}
   4.483 +
   4.484 +static void
   4.485 +ctrl_if_create_kthread(void *arg)
   4.486 +{
   4.487 +
   4.488 +	printf("ctrl_if_kthread creating\n");
   4.489 +	if (kthread_create1(ctrl_if_kthread, arg, NULL, "ctrl_if"))
   4.490 +		printf("ctrl_if_kthread create failed\n");
   4.491 +	softintr_schedule(ctrl_if_softintr);
   4.492 +}
   4.493 +
   4.494 +#ifdef notyet
   4.495 +void ctrl_if_suspend(void)
   4.496 +{
   4.497 +    free_irq(ctrl_if_irq, NULL);
   4.498 +    unbind_evtchn_from_irq(ctrl_if_evtchn);
   4.499 +}
   4.500 +#endif
   4.501 +
   4.502 +void ctrl_if_resume(void)
   4.503 +{
   4.504 +    control_if_t *ctrl_if = get_ctrl_if();
   4.505 +
   4.506 +    if ( xen_start_info.flags & SIF_INITDOMAIN )
   4.507 +    {
   4.508 +        /*
   4.509 +         * The initial domain must create its own domain-controller link.
   4.510 +         * The controller is probably not running at this point, but will
   4.511 +         * pick up its end of the event channel from 
   4.512 +         */
   4.513 +        evtchn_op_t op;
   4.514 +        op.cmd = EVTCHNOP_bind_interdomain;
   4.515 +        op.u.bind_interdomain.dom1 = DOMID_SELF;
   4.516 +        op.u.bind_interdomain.dom2 = DOMID_SELF;
   4.517 +        if ( HYPERVISOR_event_channel_op(&op) != 0 )
   4.518 +		panic("EVTCHNOP_bind_interdomain");
   4.519 +        xen_start_info.domain_controller_evtchn = op.u.bind_interdomain.port1;
   4.520 +        initdom_ctrlif_domcontroller_port   = op.u.bind_interdomain.port2;
   4.521 +    }
   4.522 +
   4.523 +    /* Sync up with shared indexes. */
   4.524 +    ctrl_if_tx_resp_cons = ctrl_if->tx_resp_prod;
   4.525 +    ctrl_if_rx_req_cons  = ctrl_if->rx_resp_prod;
   4.526 +
   4.527 +    ctrl_if_evtchn = xen_start_info.domain_controller_evtchn;
   4.528 +    ctrl_if_irq    = bind_evtchn_to_irq(ctrl_if_evtchn);
   4.529 +
   4.530 +    event_set_handler(ctrl_if_irq, &ctrl_if_interrupt, NULL, IPL_HIGH);
   4.531 +    hypervisor_enable_irq(ctrl_if_irq);
   4.532 +}
   4.533 +
   4.534 +void ctrl_if_init(void)
   4.535 +{
   4.536 +        int i;
   4.537 +
   4.538 +    for ( i = 0; i < 256; i++ )
   4.539 +        ctrl_if_rxmsg_handler[i] = ctrl_if_rxmsg_default_handler;
   4.540 +
   4.541 +    simple_lock_init(&ctrl_if_lock);
   4.542 +
   4.543 +    if (0) kthread_create(ctrl_if_create_kthread, NULL);
   4.544 +    ctrl_if_softintr =
   4.545 +	    softintr_establish(IPL_SOFTNET, ctrl_if_kthread, (void *)1);
   4.546 +
   4.547 +    ctrl_if_resume();
   4.548 +}
   4.549 +
   4.550 +
   4.551 +#if 0
   4.552 +/* This is called after it is safe to call schedule_task(). */
   4.553 +static int __init ctrl_if_late_setup(void)
   4.554 +{
   4.555 +    safe_to_schedule_task = 1;
   4.556 +    return 0;
   4.557 +}
   4.558 +__initcall(ctrl_if_late_setup);
   4.559 +#endif
   4.560 +
   4.561 +
   4.562 +/*
   4.563 + * !! The following are DANGEROUS FUNCTIONS !!
   4.564 + * Use with care [for example, see xencons_force_flush()].
   4.565 + */
   4.566 +
   4.567 +int ctrl_if_transmitter_empty(void)
   4.568 +{
   4.569 +    return (get_ctrl_if()->tx_req_prod == ctrl_if_tx_resp_cons);
   4.570 +}
   4.571 +
   4.572 +void ctrl_if_discard_responses(void)
   4.573 +{
   4.574 +    ctrl_if_tx_resp_cons = get_ctrl_if()->tx_resp_prod;
   4.575 +}
   4.576 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/netbsd-2.0-xen-sparse/sys/arch/xen/xen/evtchn.c	Mon Sep 06 19:07:17 2004 +0000
     5.3 @@ -0,0 +1,347 @@
     5.4 +/*	$NetBSD$	*/
     5.5 +
     5.6 +/*
     5.7 + *
     5.8 + * Copyright (c) 2004 Christian Limpach.
     5.9 + * Copyright (c) 2004, K A Fraser.
    5.10 + * All rights reserved.
    5.11 + *
    5.12 + * Redistribution and use in source and binary forms, with or without
    5.13 + * modification, are permitted provided that the following conditions
    5.14 + * are met:
    5.15 + * 1. Redistributions of source code must retain the above copyright
    5.16 + *    notice, this list of conditions and the following disclaimer.
    5.17 + * 2. Redistributions in binary form must reproduce the above copyright
    5.18 + *    notice, this list of conditions and the following disclaimer in the
    5.19 + *    documentation and/or other materials provided with the distribution.
    5.20 + * 3. All advertising materials mentioning features or use of this software
    5.21 + *    must display the following acknowledgement:
    5.22 + *      This product includes software developed by Christian Limpach.
    5.23 + * 4. The name of the author may not be used to endorse or promote products
    5.24 + *    derived from this software without specific prior written permission.
    5.25 + *
    5.26 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    5.27 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    5.28 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    5.29 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    5.30 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    5.31 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    5.32 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    5.33 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    5.34 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    5.35 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    5.36 + */
    5.37 +
    5.38 +
    5.39 +#include <sys/cdefs.h>
    5.40 +__KERNEL_RCSID(0, "$NetBSD$");
    5.41 +
    5.42 +#include <sys/param.h>
    5.43 +#include <sys/systm.h>
    5.44 +#include <sys/proc.h>
    5.45 +#include <sys/malloc.h>
    5.46 +#include <sys/reboot.h>
    5.47 +
    5.48 +#include <uvm/uvm.h>
    5.49 +
    5.50 +#include <machine/intrdefs.h>
    5.51 +
    5.52 +#include <machine/xen.h>
    5.53 +#include <machine/hypervisor.h>
    5.54 +#include <machine/evtchn.h>
    5.55 +#include <machine/ctrl_if.h>
    5.56 +#include <machine/xenfunc.h>
    5.57 +
    5.58 +struct pic xenev_pic = {
    5.59 +	.pic_dev = {
    5.60 +		.dv_xname = "xen_fakepic",
    5.61 +	},
    5.62 +	.pic_type = PIC_XEN,
    5.63 +	.pic_lock = __SIMPLELOCK_UNLOCKED,
    5.64 +};
    5.65 +
    5.66 +/*
    5.67 + * This lock protects updates to the following mapping and reference-count
    5.68 + * arrays. The lock does not need to be acquired to read the mapping tables.
    5.69 + */
    5.70 +static struct simplelock irq_mapping_update_lock = SIMPLELOCK_INITIALIZER;
    5.71 +
    5.72 +/* IRQ <-> event-channel mappings. */
    5.73 +int evtchn_to_irq[NR_EVENT_CHANNELS];
    5.74 +int irq_to_evtchn[NR_IRQS];
    5.75 +
    5.76 +/* IRQ <-> VIRQ mapping. */
    5.77 +static int virq_to_irq[NR_VIRQS];
    5.78 +
    5.79 +/* Reference counts for bindings to IRQs. */
    5.80 +static int irq_bindcount[NR_IRQS];
    5.81 +
    5.82 +#if 0
    5.83 +static int xen_die_handler(void *);
    5.84 +#endif
    5.85 +static int xen_debug_handler(void *);
    5.86 +static int xen_misdirect_handler(void *);
    5.87 +
    5.88 +void
    5.89 +events_default_setup()
    5.90 +{
    5.91 +	int i;
    5.92 +
    5.93 +	/* No VIRQ -> IRQ mappings. */
    5.94 +	for (i = 0; i < NR_VIRQS; i++)
    5.95 +		virq_to_irq[i] = -1;
    5.96 +
    5.97 +	/* No event-channel -> IRQ mappings. */
    5.98 +	for (i = 0; i < NR_EVENT_CHANNELS; i++) {
    5.99 +		evtchn_to_irq[i] = -1;
   5.100 +		hypervisor_mask_event(i); /* No event channels are 'live' right now. */
   5.101 +	}
   5.102 +
   5.103 +	/* No IRQ -> event-channel mappings. */
   5.104 +	for (i = 0; i < NR_IRQS; i++)
   5.105 +		irq_to_evtchn[i] = -1;
   5.106 +}
   5.107 +
   5.108 +void
   5.109 +init_events()
   5.110 +{
   5.111 +	int irq;
   5.112 +
   5.113 +	irq = bind_virq_to_irq(VIRQ_DEBUG);
   5.114 +	event_set_handler(irq, &xen_debug_handler, NULL, IPL_DEBUG);
   5.115 +	hypervisor_enable_irq(irq);
   5.116 +
   5.117 +	irq = bind_virq_to_irq(VIRQ_MISDIRECT);
   5.118 +	event_set_handler(irq, &xen_misdirect_handler, NULL, IPL_DIE);
   5.119 +	hypervisor_enable_irq(irq);
   5.120 +
   5.121 +	/* This needs to be done early, but after the IRQ subsystem is
   5.122 +	 * alive. */
   5.123 +	ctrl_if_init();
   5.124 +
   5.125 +	enable_intr();		/* at long last... */
   5.126 +}
   5.127 +
   5.128 +unsigned int
   5.129 +do_event(int irq, struct trapframe *regs)
   5.130 +{
   5.131 +	struct cpu_info *ci;
   5.132 +
   5.133 +	if (irq >= NR_IRQS) {
   5.134 +#ifdef DIAGNOSTIC
   5.135 +		printf("event irq number %d > NR_IRQS\n", irq);
   5.136 +#endif
   5.137 +		return ENOENT;
   5.138 +	}
   5.139 +
   5.140 +	if (0 && irq == 4) {
   5.141 +		ci = &cpu_info_primary;
   5.142 +		printf("do_event %d/%d called, ilevel %d\n", irq,
   5.143 +		       irq_to_evtchn[irq], ci->ci_ilevel);
   5.144 +	}
   5.145 +
   5.146 +	ci = &cpu_info_primary;
   5.147 +
   5.148 +	hypervisor_acknowledge_irq(irq);
   5.149 +	if (ci->ci_isources[irq] == NULL) {
   5.150 +		return 0;
   5.151 +	}
   5.152 +	__asm__ __volatile__ (
   5.153 +		"   movl $1f,%%esi	;"
   5.154 +		"   jmp  *%%eax		;"
   5.155 +		"1:			"
   5.156 +		: : "a" (ci->ci_isources[irq]->is_recurse),
   5.157 +		"b" (ci->ci_ilevel)
   5.158 +		: "esi", "ecx", "edx", "memory");
   5.159 +
   5.160 +	if (0 && irq == 4)
   5.161 +		printf("do_event %d done, ipending %08x\n", irq,
   5.162 +		    ci->ci_ipending);
   5.163 +
   5.164 +	return 0;
   5.165 +}
   5.166 +
   5.167 +static int
   5.168 +find_unbound_irq(void)
   5.169 +{
   5.170 +	int irq;
   5.171 +
   5.172 +	for (irq = 0; irq < NR_IRQS; irq++)
   5.173 +		if (irq_bindcount[irq] == 0)
   5.174 +			break;
   5.175 +
   5.176 +	if (irq == NR_IRQS)
   5.177 +		panic("No available IRQ to bind to: increase NR_IRQS!\n");
   5.178 +
   5.179 +	return irq;
   5.180 +}
   5.181 +
   5.182 +int
   5.183 +bind_virq_to_irq(int virq)
   5.184 +{
   5.185 +	evtchn_op_t op;
   5.186 +	int evtchn, irq;
   5.187 +
   5.188 +	simple_lock(&irq_mapping_update_lock);
   5.189 +
   5.190 +	irq = virq_to_irq[virq];
   5.191 +	if (irq == -1) {
   5.192 +		op.cmd = EVTCHNOP_bind_virq;
   5.193 +		op.u.bind_virq.virq = virq;
   5.194 +		if (HYPERVISOR_event_channel_op(&op) != 0)
   5.195 +			panic("Failed to bind virtual IRQ %d\n", virq);
   5.196 +		evtchn = op.u.bind_virq.port;
   5.197 +
   5.198 +		irq = find_unbound_irq();
   5.199 +		evtchn_to_irq[evtchn] = irq;
   5.200 +		irq_to_evtchn[irq] = evtchn;
   5.201 +
   5.202 +		virq_to_irq[virq] = irq;
   5.203 +	}
   5.204 +
   5.205 +	irq_bindcount[irq]++;
   5.206 +
   5.207 +	simple_unlock(&irq_mapping_update_lock);
   5.208 +    
   5.209 +	return irq;
   5.210 +}
   5.211 +
   5.212 +void
   5.213 +unbind_virq_from_irq(int virq)
   5.214 +{
   5.215 +	evtchn_op_t op;
   5.216 +	int irq = virq_to_irq[virq];
   5.217 +	int evtchn = irq_to_evtchn[irq];
   5.218 +
   5.219 +	simple_lock(&irq_mapping_update_lock);
   5.220 +
   5.221 +	irq_bindcount[irq]--;
   5.222 +	if (irq_bindcount[irq] == 0) {
   5.223 +		op.cmd = EVTCHNOP_close;
   5.224 +		op.u.close.dom = DOMID_SELF;
   5.225 +		op.u.close.port = evtchn;
   5.226 +		if (HYPERVISOR_event_channel_op(&op) != 0)
   5.227 +			panic("Failed to unbind virtual IRQ %d\n", virq);
   5.228 +
   5.229 +		evtchn_to_irq[evtchn] = -1;
   5.230 +		irq_to_evtchn[irq] = -1;
   5.231 +		virq_to_irq[virq] = -1;
   5.232 +	}
   5.233 +
   5.234 +	simple_unlock(&irq_mapping_update_lock);
   5.235 +}
   5.236 +
   5.237 +int bind_evtchn_to_irq(int evtchn)
   5.238 +{
   5.239 +	int irq;
   5.240 +
   5.241 +	simple_lock(&irq_mapping_update_lock);
   5.242 +
   5.243 +	irq = evtchn_to_irq[evtchn];
   5.244 +	if (irq == -1) {
   5.245 +		irq = find_unbound_irq();
   5.246 +		evtchn_to_irq[evtchn] = irq;
   5.247 +		irq_to_evtchn[irq] = evtchn;
   5.248 +	}
   5.249 +
   5.250 +	irq_bindcount[irq]++;
   5.251 +
   5.252 +	simple_unlock(&irq_mapping_update_lock);
   5.253 +    
   5.254 +	return irq;
   5.255 +}
   5.256 +
   5.257 +int
   5.258 +event_set_handler(int irq, ev_handler_t handler, void *arg, int level)
   5.259 +{
   5.260 +	struct intrsource *isp;
   5.261 +	struct intrhand *ih;
   5.262 +	struct cpu_info *ci;
   5.263 +
   5.264 +	if (irq >= NR_IRQS) {
   5.265 +#ifdef DIAGNOSTIC
   5.266 +		printf("irq number %d > NR_IRQS\n", irq);
   5.267 +#endif
   5.268 +		return ENOENT;
   5.269 +	}
   5.270 +
   5.271 +#if 0
   5.272 +	printf("event_set_handler irq %d/%d handler %p level %d\n", irq,
   5.273 +	       irq_to_evtchn[irq], handler, level);
   5.274 +#endif
   5.275 +	/* XXXcl handle already bound irq */
   5.276 +
   5.277 +	MALLOC(isp, struct intrsource *, sizeof (struct intrsource), M_DEVBUF,
   5.278 +	    M_WAITOK|M_ZERO);
   5.279 +	if (isp == NULL)
   5.280 +		panic("can't allocate fixed interrupt source");
   5.281 +	MALLOC(ih, struct intrhand *, sizeof (struct intrhand), M_DEVBUF,
   5.282 +	    M_WAITOK|M_ZERO);
   5.283 +	if (ih == NULL)
   5.284 +		panic("can't allocate fixed interrupt source");
   5.285 +
   5.286 +	ci = &cpu_info_primary;
   5.287 +
   5.288 +	isp->is_recurse = xenev_stubs[irq].ist_recurse;
   5.289 +	isp->is_resume = xenev_stubs[irq].ist_resume;
   5.290 +	ih->ih_level = level;
   5.291 +	ih->ih_fun = handler;
   5.292 +	ih->ih_arg = arg;
   5.293 +	ih->ih_next = NULL;
   5.294 +	isp->is_handlers = ih;
   5.295 +	isp->is_pic = &xenev_pic;
   5.296 +	ci->ci_isources[irq] = isp;
   5.297 +	evcnt_attach_dynamic(&isp->is_evcnt, EVCNT_TYPE_INTR, NULL,
   5.298 +	    ci->ci_dev->dv_xname, "xenev");
   5.299 +
   5.300 +	intr_calculatemasks(ci);
   5.301 +
   5.302 +	return 0;
   5.303 +}
   5.304 +
   5.305 +void hypervisor_enable_irq(unsigned int irq)
   5.306 +{
   5.307 +
   5.308 +	hypervisor_unmask_event(irq_to_evtchn[irq]);
   5.309 +}
   5.310 +
   5.311 +void hypervisor_disable_irq(unsigned int irq)
   5.312 +{
   5.313 +
   5.314 +	hypervisor_mask_event(irq_to_evtchn[irq]);
   5.315 +}
   5.316 +
   5.317 +void hypervisor_acknowledge_irq(unsigned int irq)
   5.318 +{
   5.319 +
   5.320 +	hypervisor_mask_event(irq_to_evtchn[irq]);
   5.321 +	hypervisor_clear_event(irq_to_evtchn[irq]);
   5.322 +}
   5.323 +
   5.324 +#if 0
   5.325 +static int
   5.326 +xen_die_handler(void *arg)
   5.327 +{
   5.328 +	printf("hypervisor: DIE event received...\n");
   5.329 +	cpu_reboot(0, NULL);
   5.330 +	/* NOTREACHED */
   5.331 +	return 0;
   5.332 +}
   5.333 +#endif
   5.334 +
   5.335 +static int
   5.336 +xen_debug_handler(void *arg)
   5.337 +{
   5.338 +	printf("debug event\n");
   5.339 +	return 0;
   5.340 +}
   5.341 +
   5.342 +static int
   5.343 +xen_misdirect_handler(void *arg)
   5.344 +{
   5.345 +#if 0
   5.346 +	char *msg = "misdirect\n";
   5.347 +	(void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg);
   5.348 +#endif
   5.349 +	return 0;
   5.350 +}