ia64/xen-unstable

changeset 1172:81897ae013e0

bitkeeper revision 1.788 (4051bcfbJsJbyDoBra1423PU9Gn1vA)

Merge scramble.cl.cam.ac.uk:/auto/groups/xeno/BK/xeno.bk
into scramble.cl.cam.ac.uk:/local/scratch/kaf24/xeno
author kaf24@scramble.cl.cam.ac.uk
date Fri Mar 12 13:36:59 2004 +0000 (2004-03-12)
parents 3180669cb85d 9924b21098ea
children 0920098bad91
files .rootkeys tools/examples/xc_dom_create.py tools/misc/Makefile tools/xc/lib/xc.h tools/xc/lib/xc_physdev.c tools/xc/py/Xc.c xen/arch/i386/entry.S xen/common/dom0_ops.c xen/common/domain.c xen/common/physdev.c xen/drivers/char/console.c xen/include/hypervisor-ifs/hypervisor-if.h xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h
line diff
     1.1 --- a/.rootkeys	Fri Mar 12 13:34:06 2004 +0000
     1.2 +++ b/.rootkeys	Fri Mar 12 13:36:59 2004 +0000
     1.3 @@ -79,6 +79,7 @@ 3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/xc/
     1.4  3fbba6db7li3FJiABYtCmuGxOJxEGw tools/xc/lib/xc_linux_save.c
     1.5  3fbba6db7WnnJr0KFrIFrqNlSKvFYg tools/xc/lib/xc_misc.c
     1.6  40278d9ctaHVDaEuwhXI3Om2JOjx9w tools/xc/lib/xc_netbsd_build.c
     1.7 +4051bce6CHAsYh8P5t2OHDtRWOP9og tools/xc/lib/xc_physdev.c
     1.8  3fbba6dctWRWlFJkYb6hdix2X4WMuw tools/xc/lib/xc_private.c
     1.9  3fbba6dcbVrG2hPzEzwdeV_UC8kydQ tools/xc/lib/xc_private.h
    1.10  3fbba6dcoGq9hQlksrBUfC2P5F6sGg tools/xc/lib/xc_vbd.c
    1.11 @@ -153,6 +154,7 @@ 3ddb79bdS39UXxUtZnaScie83-7VTQ xen/commo
    1.12  3ddb79bdN51qpRC-6bOH-v5hl_AK6A xen/common/network.c
    1.13  3ddb79bdD4SLmmdMD7yLW5HcUWucXw xen/common/page_alloc.c
    1.14  3e54c38dkHAev597bPr71-hGzTdocg xen/common/perfc.c
    1.15 +4051bcecFeq4DE70p4zGO5setf47CA xen/common/physdev.c
    1.16  4006e659i9j-doVxY7DKOGU4XVin1Q xen/common/rbtree.c
    1.17  3ddb79bdHqdQpATqC0rmUZNbsb6L6A xen/common/resource.c
    1.18  3e397e6619PgAfBbw2XFbXkewvUWgw xen/common/schedule.c
     2.1 --- a/tools/examples/xc_dom_create.py	Fri Mar 12 13:34:06 2004 +0000
     2.2 +++ b/tools/examples/xc_dom_create.py	Fri Mar 12 13:36:59 2004 +0000
     2.3 @@ -85,6 +85,7 @@ image=''; ramdisk=''; builder_fn=''; res
     2.4  mem_size=0; domain_name=''; vfr_ipaddr=[];
     2.5  vbd_expert=0; auto_restart=False;
     2.6  vbd_list = []; cmdline_ip = ''; cmdline_root=''; cmdline_extra=''
     2.7 +pci_device_list = []
     2.8  
     2.9  ##### Determine location of defautls file
    2.10  #####
    2.11 @@ -278,6 +279,14 @@ def make_domain():
    2.12      for ip in vfr_ipaddr:
    2.13  	XenoUtil.setup_vfr_rules_for_vif( id, 0, ip )
    2.14  
    2.15 +    # check for physical device access
    2.16 +    for (pci_bus, pci_dev, pci_func) in pci_device_list:
    2.17 +        if xc.physdev_pci_access_modify(
    2.18 +            dom=id, bus=pci_bus, dev=pci_dev, func=pci_func, enable=1 ) < 0:
    2.19 +            print "Non-fatal error enabling PCI device access."
    2.20 +        else:
    2.21 +            print "Enabled PCI access (%d:%d:%d)." % (pci_bus,pci_dev,pci_func)
    2.22 +
    2.23      if xc.domain_start( dom=id ) < 0:
    2.24          print "Error starting domain"
    2.25          xc.domain_destroy ( dom=id )
     3.1 --- a/tools/misc/Makefile	Fri Mar 12 13:34:06 2004 +0000
     3.2 +++ b/tools/misc/Makefile	Fri Mar 12 13:36:59 2004 +0000
     3.3 @@ -16,18 +16,14 @@ all: $(TARGETS)
     3.4  
     3.5  install: all
     3.6  	mkdir -p $(prefix)/usr/bin
     3.7 -	cp -a $(INSTALL) $(prefix)/usr/bin
     3.8 -	chmod 755 $(prefix)/usr/bin/xen-mkdevnodes
     3.9 -	chmod 755 $(prefix)/usr/bin/xen_nat_enable
    3.10 -	chmod 755 $(prefix)/usr/bin/xen-clone
    3.11 +	cp $(INSTALL) $(prefix)/usr/bin
    3.12 +	for i in $(INSTALL); do chmod 755 $(prefix)/usr/bin/$i ; done
    3.13  	$(MAKE) -C miniterm install
    3.14  
    3.15  dist: all
    3.16  	mkdir -p ../../../install/bin
    3.17 -	cp -a $(INSTALL) ../../../install/bin
    3.18 -	chmod 755 ../../../install/bin/xen-mkdevnodes
    3.19 -	chmod 755 ../../../install/bin/xen_nat_enable
    3.20 -	chmod 755 ../../../install/bin/xen-clone
    3.21 +	cp $(INSTALL) ../../../install/bin
    3.22 +	for i in $(INSTALL); do chmod 755 ../../../install/bin/$i ; done
    3.23  	$(MAKE) -C miniterm dist
    3.24  
    3.25  clean:
     4.1 --- a/tools/xc/lib/xc.h	Fri Mar 12 13:34:06 2004 +0000
     4.2 +++ b/tools/xc/lib/xc.h	Fri Mar 12 13:36:59 2004 +0000
     4.3 @@ -178,6 +178,13 @@ int xc_evtchn_status(int xc_handle,
     4.4                       int *port2,
     4.5                       int *chn_status);
     4.6  
     4.7 +int xc_physdev_pci_access_modify(int xc_handle,
     4.8 +                                 u64 domid,
     4.9 +                                 int bus,
    4.10 +                                 int dev,
    4.11 +                                 int func,
    4.12 +                                 int enable);
    4.13 +
    4.14  int xc_readconsolering(int xc_handle,
    4.15                         char *str, 
    4.16                         unsigned int max_chars, 
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/xc/lib/xc_physdev.c	Fri Mar 12 13:36:59 2004 +0000
     5.3 @@ -0,0 +1,27 @@
     5.4 +/******************************************************************************
     5.5 + * xc_physdev.c
     5.6 + * 
     5.7 + * API for manipulating physical-device access permissions.
     5.8 + * 
     5.9 + * Copyright (c) 2004, Rolf Neugebauer (Intel Research Cambridge)
    5.10 + * Copyright (c) 2004, K A Fraser (University of Cambridge)
    5.11 + */
    5.12 +
    5.13 +int xc_physdev_pci_access_modify(int xc_handle,
    5.14 +                                 u64 domid,
    5.15 +                                 int bus,
    5.16 +                                 int dev,
    5.17 +                                 int func,
    5.18 +                                 int enable)
    5.19 +{
    5.20 +    dom0_op_t op;
    5.21 +
    5.22 +    op.cmd = DOM0_PCIDEV_ACCESS;
    5.23 +    op.u.pcidev_access.domain = (domid_t)domid;
    5.24 +    op.u.pcidev_access.bus    = bus;
    5.25 +    op.u.pcidev_access.dev    = dev;
    5.26 +    op.u.pcidev_access.func   = func;
    5.27 +    op.u.pcidev_access.enable = enable;
    5.28 +
    5.29 +    return do_dom0_op(xc_handle, &op);
    5.30 +}
     6.1 --- a/tools/xc/py/Xc.c	Fri Mar 12 13:34:06 2004 +0000
     6.2 +++ b/tools/xc/py/Xc.c	Fri Mar 12 13:36:59 2004 +0000
     6.3 @@ -892,6 +892,29 @@ static PyObject *pyxc_evtchn_status(PyOb
     6.4      return dict;
     6.5  }
     6.6  
     6.7 +static PyObject *pyxc_physdev_pci_access_modify(PyObject *self,
     6.8 +                                                PyObject *args,
     6.9 +                                                PyObject *kwds)
    6.10 +{
    6.11 +    XcObject *xc = (XcObject *)self;
    6.12 +    u64 dom;
    6.13 +    int bus, dev, func, enable, ret;
    6.14 +
    6.15 +    static char *kwd_list[] = { "dom", "bus", "dev", "func", "enable", NULL };
    6.16 +
    6.17 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Liiii", kwd_list, 
    6.18 +                                      &dom, &bus, &dev, &func, &enable) )
    6.19 +    {
    6.20 +        DPRINTF("could not parse parameter list.");
    6.21 +        return NULL;
    6.22 +    }
    6.23 +
    6.24 +    ret = xc_physdev_pci_access_modify(
    6.25 +        xc->xc_handle, dom, bus, dev, func, enable);
    6.26 +    
    6.27 +    return PyInt_FromLong(ret);
    6.28 +}
    6.29 +
    6.30  static PyObject *pyxc_readconsolering(PyObject *self,
    6.31                                        PyObject *args,
    6.32                                        PyObject *kwds)
    6.33 @@ -924,9 +947,7 @@ static PyObject *pyxc_physinfo(PyObject 
    6.34      int xc_ret;
    6.35      xc_physinfo_t info;
    6.36      
    6.37 -    xc_ret = xc_physinfo(xc->xc_handle, &info);
    6.38 -
    6.39 -    if(!xc_ret)
    6.40 +    if ( (xc_ret = xc_physinfo(xc->xc_handle, &info)) == 0 )
    6.41      {
    6.42          ret_obj = Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
    6.43                                  "ht_per_core", info.ht_per_core,
    6.44 @@ -937,7 +958,8 @@ static PyObject *pyxc_physinfo(PyObject 
    6.45      }
    6.46      else
    6.47      {
    6.48 -        ret_obj = Py_BuildValue(""); /* None */
    6.49 +        Py_INCREF(Py_None);
    6.50 +        ret_obj = Py_None;
    6.51      }
    6.52      
    6.53      return ret_obj;
    6.54 @@ -978,7 +1000,7 @@ static PyMethodDef pyxc_methods[] = {
    6.55        (PyCFunction)pyxc_domain_pincpu, 
    6.56        METH_VARARGS | METH_KEYWORDS, "\n"
    6.57        "Pin a domain to a specified CPU.\n"
    6.58 -      " dom [long]:    Identifier of domain to be destroyed.\n"
    6.59 +      " dom [long]:    Identifier of domain to be pinned.\n"
    6.60        " cpu [int, -1]: CPU to pin to, or -1 to unpin\n\n"
    6.61        "Returns: [int] 0 on success; -1 on error.\n" },
    6.62  
    6.63 @@ -1195,6 +1217,17 @@ static PyMethodDef pyxc_methods[] = {
    6.64        " dom  [long]: Port-id for endpoint at dom1.\n"
    6.65        " port [int]:  Port-id for endpoint at dom2.\n" },
    6.66  
    6.67 +    { "physdev_pci_access_modify",
    6.68 +      (PyCFunction)pyxc_physdev_pci_access_modify,
    6.69 +      METH_VARARGS | METH_KEYWORDS, "\n"
    6.70 +      "Allow a domain access to a PCI device\n"
    6.71 +      " dom    [long]: Identifier of domain to be allowed access.\n"
    6.72 +      " bus    [int]:  PCI bus\n"
    6.73 +      " dev    [int]:  PCI slot\n"
    6.74 +      " func   [int]:  PCI function\n"
    6.75 +      " enable [int]:  Non-zero means enable access; else disable access\n\n"
    6.76 +      "Returns: [int] 0 on success; -1 on error.\n" },
    6.77 + 
    6.78      { "readconsolering", 
    6.79        (PyCFunction)pyxc_readconsolering, 
    6.80        METH_VARARGS | METH_KEYWORDS, "\n"
     7.1 --- a/xen/arch/i386/entry.S	Fri Mar 12 13:34:06 2004 +0000
     7.2 +++ b/xen/arch/i386/entry.S	Fri Mar 12 13:36:59 2004 +0000
     7.3 @@ -727,7 +727,8 @@ ENTRY(hypervisor_call_table)
     7.4          .long SYMBOL_NAME(do_set_timer_op)       /* 20 */
     7.5          .long SYMBOL_NAME(do_event_channel_op)
     7.6          .long SYMBOL_NAME(do_xen_version)
     7.7 -        .long SYMBOL_NAME(do_serial_io)
     7.8 +        .long SYMBOL_NAME(do_console_io)
     7.9 +        .long SYMBOL_NAME(do_physdev_op)
    7.10          .rept NR_syscalls-((.-hypervisor_call_table)/4)
    7.11          .long SYMBOL_NAME(do_ni_syscall)
    7.12          .endr
     8.1 --- a/xen/common/dom0_ops.c	Fri Mar 12 13:34:06 2004 +0000
     8.2 +++ b/xen/common/dom0_ops.c	Fri Mar 12 13:36:59 2004 +0000
     8.3 @@ -473,6 +473,17 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     8.4      }
     8.5      break;
     8.6      
     8.7 +    case DOM0_PCIDEV_ACCESS:
     8.8 +    {
     8.9 +        extern int physdev_pci_access_modify(domid_t, int, int, int, int);
    8.10 +        ret = physdev_pci_access_modify(op->u.pcidev_access.domain, 
    8.11 +                                        op->u.pcidev_access.bus,
    8.12 +                                        op->u.pcidev_access.dev,
    8.13 +                                        op->u.pcidev_access.func,
    8.14 +                                        op->u.pcidev_access.enable);
    8.15 +    }
    8.16 +    break;
    8.17 +     
    8.18      default:
    8.19          ret = -ENOSYS;
    8.20  
     9.1 --- a/xen/common/domain.c	Fri Mar 12 13:34:06 2004 +0000
     9.2 +++ b/xen/common/domain.c	Fri Mar 12 13:36:59 2004 +0000
     9.3 @@ -74,6 +74,10 @@ struct task_struct *do_createdomain(domi
     9.4          
     9.5          init_blkdev_info(p);
     9.6          
     9.7 +        /* Per-domain PCI-device list. */
     9.8 +        spin_lock_init(&p->pcidev_lock);
     9.9 +        INIT_LIST_HEAD(&p->pcidev_list);
    9.10 +
    9.11          write_lock_irqsave(&tasklist_lock, flags);
    9.12          pp = &task_list; /* NB. task_list is maintained in order of dom_id. */
    9.13          for ( pp = &task_list; *pp != NULL; pp = &(*pp)->next_list )
    9.14 @@ -837,6 +841,9 @@ int setup_guestos(struct task_struct *p,
    9.15      }
    9.16      kfree(xd);
    9.17  
    9.18 +    /* DOM0 gets access to everything. */
    9.19 +    physdev_init_dom0(p);
    9.20 +
    9.21      set_bit(PF_CONSTRUCTED, &p->flags);
    9.22  
    9.23      new_thread(p, 
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xen/common/physdev.c	Fri Mar 12 13:36:59 2004 +0000
    10.3 @@ -0,0 +1,815 @@
    10.4 +/* -*-  Mode:C; c-basic-offset:4; tab-width:4 -*-
    10.5 + ****************************************************************************
    10.6 + * (C) 2004 - Rolf Neugebauer - Intel Research Cambridge
    10.7 + ****************************************************************************
    10.8 + *
    10.9 + *        File: phys_dev.c
   10.10 + *      Author: Rolf Neugebauer (rolf.neugebauer@intel.com)
   10.11 + *        Date: Feb 2004
   10.12 + * 
   10.13 + * Description: allows a domain to access devices on the PCI bus
   10.14 + *
   10.15 + * a guest os may be given access to particular devices on the PCI
   10.16 + * bus. to allow the standard PCI device discovery to work it may
   10.17 + * also have limited access to devices (bridges) in the PCI device
   10.18 + * tree between the device and the PCI root device.
   10.19 + *
   10.20 + * for each domain a list of PCI devices is maintained, describing the
   10.21 + * access mode for the domain. 
   10.22 + *
   10.23 + * guests can figure out the virtualised, or better, partioned PCI space
   10.24 + * through normal pci config register access. Some of the accesses, in
   10.25 + * particular write access are faked out. For example the sequence for
   10.26 + * for detecting the IO regions, which require writes to determine the
   10.27 + * size of teh region, is faked out by a very simple state machine, 
   10.28 + * preventing direct writes to the PCI config registers by a guest.
   10.29 + *
   10.30 + * XXX Some comment on IRQ handling
   10.31 + */
   10.32 +
   10.33 +
   10.34 +#include <xeno/config.h>
   10.35 +#include <xeno/lib.h>
   10.36 +#include <xeno/types.h>
   10.37 +#include <xeno/sched.h>
   10.38 +#include <xeno/pci.h>
   10.39 +#include <xeno/irq.h>
   10.40 +#include <xeno/event.h>
   10.41 +
   10.42 +#include <asm/pci.h>
   10.43 +
   10.44 +
   10.45 +#include <hypervisor-ifs/hypervisor-if.h>
   10.46 +#include <hypervisor-ifs/phys_dev.h>
   10.47 +
   10.48 +#define DBG(_x...)
   10.49 +//#define DBG(_x...) printk(_x)
   10.50 +
   10.51 +#define ACC_READ  1
   10.52 +#define ACC_WRITE 2
   10.53 +
   10.54 +/* upper bounds for PCI  devices */
   10.55 +#define PCI_BUSMAX  255
   10.56 +#define PCI_DEVMAX   31
   10.57 +#define PCI_FUNCMAX   7
   10.58 +#define PCI_REGMAX  255
   10.59 +
   10.60 +/* bit offsets into state */
   10.61 +#define ST_BASE_ADDRESS  0   /* bits 0-5: are for base address access */
   10.62 +#define ST_ROM_ADDRESS   6   /* bit 6: is for rom address access */    
   10.63 +#define ST_IRQ_DELIVERED 7   /* bit 7: waiting for end irq call */    
   10.64 +
   10.65 +
   10.66 +typedef struct _phys_dev_st
   10.67 +{
   10.68 +    int flags;                       /* flags for access etc */
   10.69 +    struct pci_dev *dev;             /* the device */
   10.70 +    struct list_head node;           /* link to the list */
   10.71 +    struct task_struct *owner;       /* 'owner of this device' */
   10.72 +    int state;                       /* state for various checks */
   10.73 +
   10.74 +    hw_irq_controller *new_handler;  /* saved old handler */
   10.75 +    hw_irq_controller *orig_handler; /* saved old handler */
   10.76 +
   10.77 +} phys_dev_t;
   10.78 +
   10.79 +
   10.80 +#define MAX_IRQS 32
   10.81 +/* an array of device descriptors index by IRQ number */
   10.82 +static phys_dev_t *irqs[MAX_IRQS];
   10.83 +
   10.84 +/* find a device on the device list */
   10.85 +static phys_dev_t *find_pdev(struct task_struct *p, struct pci_dev *dev)
   10.86 +{
   10.87 +    phys_dev_t *t, *res = NULL;
   10.88 +    struct list_head *tmp;
   10.89 +
   10.90 +    list_for_each(tmp, &p->dev_list)
   10.91 +    {
   10.92 +        t = list_entry(tmp,  phys_dev_t, node);
   10.93 +        if ( dev == t->dev )
   10.94 +        {
   10.95 +            res = t;
   10.96 +            break;
   10.97 +        }
   10.98 +    }
   10.99 +    return res;
  10.100 +}
  10.101 +
  10.102 +/* add the device to the list of devices task p can access */
  10.103 +static void add_dev_to_task(struct task_struct *p, 
  10.104 +                            struct pci_dev *dev, int acc)
  10.105 +{
  10.106 +    
  10.107 +    phys_dev_t *pdev;
  10.108 +    
  10.109 +    if ( (pdev = find_pdev(p, dev)) )
  10.110 +    {
  10.111 +        /* device already on list, update access  */
  10.112 +        pdev->flags = acc;
  10.113 +        return;
  10.114 +    }
  10.115 +
  10.116 +    /* add device */
  10.117 +    if ( !(pdev = kmalloc(sizeof(phys_dev_t), GFP_KERNEL)) )
  10.118 +    {
  10.119 +        printk("error allocating pdev structure\n");
  10.120 +        return;
  10.121 +    }
  10.122 +    
  10.123 +    pdev->dev = dev;
  10.124 +    pdev->flags = acc;
  10.125 +    pdev->state = 0;
  10.126 +    list_add(&pdev->node, &p->dev_list);
  10.127 +
  10.128 +    if ( acc == ACC_WRITE )
  10.129 +        pdev->owner = p;
  10.130 +
  10.131 +}
  10.132 +
  10.133 +/*
  10.134 + * physdev_pci_access_modify:
  10.135 + * Allow/disallow access to a specific PCI device. Also allow read access to 
  10.136 + * PCI devices from the device to the root of the device tree. If the given 
  10.137 + * device is a bridge, then the domain should get access to all the devices 
  10.138 + * attached to that bridge (XXX this is unimplemented!).
  10.139 + */
  10.140 +int physdev_pci_access_modify(
  10.141 +    domid_t dom, int bus, int dev, int func, int enable)
  10.142 +{
  10.143 +    struct task_struct *p;
  10.144 +    struct pci_dev *pdev, *rdev, *tdev;
  10.145 + 
  10.146 +    if ( !IS_PRIV(current) )
  10.147 +        BUG();
  10.148 +
  10.149 +    if ( (bus > PCI_BUSMAX) || (dev > PCI_DEVMAX) || (func > PCI_FUNCMAX) )
  10.150 +        return -EINVAL;
  10.151 +
  10.152 +    if ( !enable )
  10.153 +    {
  10.154 +        DPRINTK("Disallowing access is not yet supported.\n");
  10.155 +        return -EINVAL;
  10.156 +    }
  10.157 +
  10.158 +    DPRINTK("physdev_pci_access_modify: %02x:%02x:%02x\n", bus, dev, func);
  10.159 +
  10.160 +    if ( (p = find_domain_by_id(dom) == NULL ) 
  10.161 +        return -ESRCH;
  10.162 +
  10.163 +    /* Make the domain privileged. */
  10.164 +    set_bit(PF_PRIVILEGED, &p->flags); 
  10.165 +
  10.166 +    /* Grant write access to the specified device. */
  10.167 +    if ( (pdev = pci_find_slot(bus, PCI_DEVFN(dev, func))) == NULL )
  10.168 +    {
  10.169 +        DPRINTK("  dev does not exist\n");
  10.170 +        return -ENODEV;
  10.171 +    }
  10.172 +    add_dev_to_task(p, pdev, ACC_WRITE);
  10.173 +    DPRINTK("  add RW %02x:%02x:%02x\n", pdev->bus->number,
  10.174 +            PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
  10.175 +
  10.176 +
  10.177 +    /* Grant read access to the root device. */
  10.178 +    if ( (rdev = pci_find_slot(0, PCI_DEVFN(0, 0))) == NULL )
  10.179 +    {
  10.180 +        DPRINTK("  bizarre -- no PCI root dev\n");
  10.181 +        return -ENODEV;
  10.182 +    }
  10.183 +    add_dev_to_task(p, rdev, ACC_READ);
  10.184 +    DPRINTK("  add R0 %02x:%02x:%02x\n", 0, 0, 0);
  10.185 +
  10.186 +    /* Grant read access to all devices on the path to the root. */
  10.187 +    while ( tdev = pdev->bus->self; tdev != NULL; tdev = tdev->bus->self )
  10.188 +    {
  10.189 +        add_dev_to_task(p, tdev, ACC_READ);
  10.190 +        DPRINTK("  add RO %02x:%02x:%02x\n", tdev->bus->number,
  10.191 +                PCI_SLOT(tdev->devfn), PCI_FUNC(tdev->devfn));
  10.192 +    }
  10.193 +
  10.194 +    if ( pdev->hdr_type == PCI_HEADER_TYPE_NORMAL )
  10.195 +        return 0;
  10.196 +    
  10.197 +    /* The  device is a bridge or cardbus. */
  10.198 +    printk("XXX can't give access to bridge devices yet\n");
  10.199 +
  10.200 +    return 0;
  10.201 +}
  10.202 +
  10.203 +/* check if a domain has general access to a device */
  10.204 +inline static int check_dev_acc (struct task_struct *p,
  10.205 +                                 int bus, int dev, int func,
  10.206 +                                 phys_dev_t **pdev) 
  10.207 +{
  10.208 +    struct pci_dev *target_dev;
  10.209 +    phys_dev_t     *target_pdev;
  10.210 +    unsigned int    target_devfn;
  10.211 +
  10.212 +    *pdev = NULL;
  10.213 +
  10.214 +    if ( !IS_PRIV(p) )
  10.215 +        return -EPERM; /* no pci acces permission */
  10.216 +
  10.217 +    if ( bus > PCI_BUSMAX || dev > PCI_DEVMAX || func > PCI_FUNCMAX )
  10.218 +        return -EINVAL;
  10.219 +
  10.220 +    DBG("a=%c b=%x d=%x f=%x ", (acc == ACC_READ) ? 'R' : 'W',
  10.221 +        mask, bus, dev, func);
  10.222 +
  10.223 +    /* check target device */
  10.224 +    target_devfn = PCI_DEVFN(dev, func);
  10.225 +    target_dev   = pci_find_slot(bus, target_devfn);
  10.226 +    if ( !target_dev )
  10.227 +    {
  10.228 +        DBG("target does not exist\n");
  10.229 +        return -ENODEV;
  10.230 +    }
  10.231 +
  10.232 +    /* check access */
  10.233 +    target_pdev = find_pdev(p, target_dev);
  10.234 +    if ( !target_pdev )
  10.235 +    {
  10.236 +        DBG("dom has no access to target\n");
  10.237 +        return -EPERM;
  10.238 +    }
  10.239 +
  10.240 +    *pdev = target_pdev;
  10.241 +    return 0;
  10.242 +}
  10.243 +
  10.244 +
  10.245 +/*
  10.246 + * Base address registers contain the base address for IO regions.
  10.247 + * The length can be determined by writing all 1s to the register and
  10.248 + * reading the value again. The device will zero the lower unused bits.
  10.249 + * 
  10.250 + * to work out the length of the io region a device probe typically does:
  10.251 + * 1) a = read_base_addr_reg()
  10.252 + * 2) write_base_addr_reg(0xffffffff)
  10.253 + * 3) b = read_base_addr_reg() // device zeros lower bits
  10.254 + * 4) write_base_addr_reg(a) // restore original value
  10.255 + * this function fakes out step 2-4. *no* writes are made to the device.
  10.256 + * 
  10.257 + * phys_dev_t contains a bit field (a bit for each base address register).
  10.258 + * if the bit for a register is set the guest had writen all 1s to the 
  10.259 + * register and subsequent read request need to fake out the b.
  10.260 + * if the guest restores the original value (step 4 above) the bit is
  10.261 + * cleared again. If the guest attempts to "restores" a wrong value an
  10.262 + * error is flagged.
  10.263 + */
  10.264 +static int do_base_address_access(phys_dev_t *pdev, int acc,
  10.265 +                                  int seg, int bus, int dev, int func, 
  10.266 +                                  int reg, int len, u32 *val)
  10.267 +{
  10.268 +    int idx, st_bit, ret = -EINVAL;
  10.269 +    u32 orig_val, sz;
  10.270 +    struct resource *res;
  10.271 +
  10.272 +    idx    = (reg - PCI_BASE_ADDRESS_0)/4;
  10.273 +    st_bit = idx + ST_BASE_ADDRESS;
  10.274 +    res    = &(pdev->dev->resource[idx]);
  10.275 +
  10.276 +    if ( acc == ACC_WRITE )
  10.277 +    {
  10.278 +        if ( *val == 0xffffffff || 
  10.279 +             ((res->flags & IORESOURCE_IO) && *val == 0xffff) )
  10.280 +        {
  10.281 +            /* set bit and return */
  10.282 +            set_bit(st_bit, &pdev->state);
  10.283 +            ret = 0;
  10.284 +        }
  10.285 +        else
  10.286 +        {
  10.287 +            /* assume guest wants to set the base address */
  10.288 +            clear_bit(st_bit, &pdev->state);
  10.289 +
  10.290 +            /* check if guest tries to restore orig value */
  10.291 +            ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
  10.292 +            if ( *val != orig_val ) 
  10.293 +            {
  10.294 +                printk("caution: guest tried to change base address range.\n");
  10.295 +                ret = -EPERM;
  10.296 +            }
  10.297 +        }
  10.298 +        DBG("fixed pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x"
  10.299 +            " val=0x%08x %lx\n", bus, dev, func, reg, len, *val,
  10.300 +            pdev->state);
  10.301 +
  10.302 +    }
  10.303 +
  10.304 +    else if ( acc == ACC_READ )
  10.305 +    {
  10.306 +        if ( !test_bit(st_bit, &pdev->state) )
  10.307 +        {
  10.308 +            /* just read and return */
  10.309 +            ret = pci_config_read(seg, bus, dev, func, reg, len, val);
  10.310 +        }
  10.311 +        else
  10.312 +        {
  10.313 +            /* fake value */
  10.314 +            ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
  10.315 +
  10.316 +            sz  = res->end - res->start;
  10.317 +
  10.318 +            if ( res->flags & IORESOURCE_MEM )
  10.319 +            {
  10.320 +                *val = 0xffffffff;
  10.321 +                /* bit    0 = 0 */
  10.322 +                /* bit  21  = memory type */
  10.323 +                /* bit 3    = prefetchable */
  10.324 +                /* bit 4-31 width */
  10.325 +                sz   = sz >> 4; /* size in blocks of 16 byte */
  10.326 +                sz   = ~sz;     /* invert */
  10.327 +                *val = *val & (sz << 4); /* and in the size */
  10.328 +                /* use read values for low 4 bits */
  10.329 +                *val = *val | (orig_val & 0xf);
  10.330 +            }
  10.331 +            else if ( res->flags & IORESOURCE_IO )
  10.332 +            {
  10.333 +                *val = 0x0000ffff;
  10.334 +                /* bit 10 = 01 */
  10.335 +                /* bit 2-31 width */
  10.336 +                sz   = sz >> 2; /* size in dwords */
  10.337 +                sz   = ~sz & 0x0000ffff;
  10.338 +                *val = *val & (sz << 2);
  10.339 +                *val = *val | 0x1;
  10.340 +            }
  10.341 +            ret = 0;
  10.342 +        }
  10.343 +        DBG("fixed pci read : %02x:%02x:%02x reg=0x%02x len=0x%02x"
  10.344 +            " val=0x%08x %lx\n", bus, dev, func, reg, len, *val, pdev->state);
  10.345 +    }
  10.346 +
  10.347 +    return ret;
  10.348 +}
  10.349 +
  10.350 +/*
  10.351 + * fake out read/write access to rom address register
  10.352 + * pretty much the same as a above
  10.353 + */
  10.354 +static int do_rom_address_access(phys_dev_t *pdev, int acc,
  10.355 +                                  int seg, int bus, int dev, int func, 
  10.356 +                                  int reg, int len, u32 *val)
  10.357 +{
  10.358 +    int st_bit, ret = -EINVAL;
  10.359 +    u32 orig_val, sz;
  10.360 +    struct resource *res;
  10.361 +
  10.362 +    st_bit = ST_ROM_ADDRESS;
  10.363 +    res = &(pdev->dev->resource[PCI_ROM_RESOURCE]);
  10.364 +
  10.365 +    if ( acc == ACC_WRITE )
  10.366 +    {
  10.367 +        if ( *val == 0xffffffff || *val == 0xfffffffe)
  10.368 +        {
  10.369 +            /* 0xffffffff would be unusual, but we check anyway */
  10.370 +            /* set bit and return */
  10.371 +            set_bit(st_bit, &pdev->state);
  10.372 +            ret = 0;
  10.373 +        }
  10.374 +        else
  10.375 +        {
  10.376 +            /* assume guest wants to set the base address */
  10.377 +            clear_bit(st_bit, &pdev->state);
  10.378 +            
  10.379 +            /* check if guest tries to restore orig value */
  10.380 +            ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
  10.381 +            if ( (*val != orig_val) ) 
  10.382 +            {
  10.383 +                if (*val != 0x00000000 )
  10.384 +                {
  10.385 +                    printk("caution: guest tried to change rom address.\n");
  10.386 +                    ret = -EPERM;
  10.387 +                }
  10.388 +                else
  10.389 +                {
  10.390 +                    printk ("guest disabled rom access for %02x:%02x:%02x\n",
  10.391 +                            bus, dev, func);
  10.392 +                    ret = 0;
  10.393 +                }
  10.394 +            }
  10.395 +
  10.396 +        }
  10.397 +        DBG("fixed pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x"
  10.398 +            " val=0x%08x %lx\n", bus, dev, func, reg, len, *val, pdev->state);
  10.399 +     
  10.400 +    }
  10.401 +    else if ( acc == ACC_READ )
  10.402 +    {
  10.403 +       if ( !test_bit(st_bit, &pdev->state) )
  10.404 +        {
  10.405 +            /* just read and return */
  10.406 +            ret = pci_config_read(seg, bus, dev, func, reg, len, val);
  10.407 +        }
  10.408 +        else
  10.409 +        {
  10.410 +            /* fake value */
  10.411 +            ret = pci_config_read(seg, bus, dev, func, reg, len, &orig_val);
  10.412 +            sz  = res->end - res->start;
  10.413 +            *val = 0xffffffff;
  10.414 +            /* leave bit 0 untouched */
  10.415 +            /* bit 1-10 reserved, harwired to 0 */
  10.416 +            sz = sz >> 11; /* size is in 2KB blocks */
  10.417 +            sz = ~sz;
  10.418 +            *val = *val & (sz << 11);
  10.419 +            *val = *val | (orig_val & 0x1);
  10.420 +        }
  10.421 +
  10.422 +        DBG("fixed pci read : %02x:%02x:%02x reg=0x%02x len=0x%02x"
  10.423 +            " val=0x%08x %lx\n", bus, dev, func, reg, len, *val, pdev->state);
  10.424 +    }
  10.425 +    return ret;
  10.426 +
  10.427 +}
  10.428 +
  10.429 +/*
  10.430 + * handle a domains pci config space read access if it has access to
  10.431 + * the device.
  10.432 + * For some registers for read-only devices (e.g. address base registers)
  10.433 + * we need to maintain a state machine.
  10.434 + */
  10.435 +static long pci_cfgreg_read(int seg, int bus, int dev, int func, int reg,
  10.436 +                            int len, u32 *val)
  10.437 +{
  10.438 +    int ret = 0;
  10.439 +    phys_dev_t *pdev;
  10.440 +
  10.441 +    ret = check_dev_acc(current, bus, dev, func, &pdev);
  10.442 +    if ( ret != 0 )
  10.443 +        return ret;
  10.444 +
  10.445 +    /* fake out read requests for some registers */
  10.446 +    switch (reg)
  10.447 +    {
  10.448 +    case PCI_BASE_ADDRESS_0:
  10.449 +    case PCI_BASE_ADDRESS_1:
  10.450 +    case PCI_BASE_ADDRESS_2:
  10.451 +    case PCI_BASE_ADDRESS_3:
  10.452 +    case PCI_BASE_ADDRESS_4:
  10.453 +    case PCI_BASE_ADDRESS_5:
  10.454 +        ret = do_base_address_access (pdev, ACC_READ, seg, bus, dev, 
  10.455 +                                      func, reg, len, val);
  10.456 +        return ret;
  10.457 +        break;
  10.458 +    case PCI_ROM_ADDRESS:
  10.459 +        ret = do_rom_address_access (pdev, ACC_READ, seg, bus, dev, 
  10.460 +                                      func, reg, len, val);
  10.461 +        return ret;
  10.462 +        break;        
  10.463 +    default:
  10.464 +        break;
  10.465 +    }
  10.466 +
  10.467 +    ret = pci_config_read(seg, bus, dev, func, reg, len, val);
  10.468 +
  10.469 +    DBG("pci read : %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n",
  10.470 +        bus, dev, func, reg, len, *val);
  10.471 +    return ret;
  10.472 +}
  10.473 +
  10.474 +/*
  10.475 + * handle a domains pci config space write accesses if it has access to
  10.476 + * the device.
  10.477 + * for some registers a state machine is maintained to fake out r/w access.
  10.478 + * By default no write access is allowed but we may change that in the future.
  10.479 + */
  10.480 +static long pci_cfgreg_write(int seg, int bus, int dev, int func, int reg,
  10.481 +                             int len, u32 val)
  10.482 +{
  10.483 +    int ret = 0;
  10.484 +    phys_dev_t *pdev;
  10.485 +
  10.486 +    ret = check_dev_acc(current, bus, dev, func, &pdev);
  10.487 +    if ( ret != 0 )
  10.488 +        return ret;
  10.489 +
  10.490 +    /* special treatment for some registers */
  10.491 +    switch (reg)
  10.492 +    {
  10.493 +    case PCI_BASE_ADDRESS_0:
  10.494 +    case PCI_BASE_ADDRESS_1:
  10.495 +    case PCI_BASE_ADDRESS_2:
  10.496 +    case PCI_BASE_ADDRESS_3:
  10.497 +    case PCI_BASE_ADDRESS_4:
  10.498 +    case PCI_BASE_ADDRESS_5:
  10.499 +        ret = do_base_address_access (pdev, ACC_WRITE, seg, bus, dev, 
  10.500 +                                      func, reg, len, &val);
  10.501 +        return ret;
  10.502 +        break;
  10.503 +    case PCI_ROM_ADDRESS:
  10.504 +        ret = do_rom_address_access (pdev, ACC_WRITE, seg, bus, dev, 
  10.505 +                                      func, reg, len, &val);
  10.506 +        return ret;
  10.507 +        break;        
  10.508 +    default:
  10.509 +        //if ( pdev->flags != ACC_WRITE ) 
  10.510 +        /* XXX for debug we disallow all write access */
  10.511 +        {
  10.512 +            printk("pci write not allowed %02x:%02x:%02x: "
  10.513 +                   "reg=0x%02x len=0x%02x val=0x%08x\n",
  10.514 +                   bus, dev, func, reg, len, val);
  10.515 +            return -EPERM;
  10.516 +        }
  10.517 +        break;
  10.518 +    }
  10.519 +
  10.520 +    ret = pci_config_write(seg, bus, dev, func, reg, len, val);
  10.521 +
  10.522 +    DBG("pci write: %02x:%02x:%02x reg=0x%02x len=0x%02x val=0x%08x\n",
  10.523 +        bus, dev, func, reg, len, val);
  10.524 +    return ret;
  10.525 +}
  10.526 +
  10.527 +
  10.528 +/*
  10.529 + * return the IRQ xen assigned to the device.
  10.530 + * This may be different to what is in the PCI confic space!
  10.531 + * XXX RN: I'm not sure we need this. we could just intercept PCI config
  10.532 + * reads on PCI_INTERRUPT_LINE and return the correct value.
  10.533 + */
  10.534 +static long pci_find_irq(int seg, int bus, int dev, int func, u32 *val)
  10.535 +{
  10.536 +    int ret = 0;
  10.537 +    phys_dev_t *pdev;
  10.538 +
  10.539 +    ret = check_dev_acc(current, bus, dev, func, &pdev);
  10.540 +    if ( ret != 0 )
  10.541 +        return ret;
  10.542 +
  10.543 +    *val = pdev->dev->irq;
  10.544 +    return 0;
  10.545 +}
  10.546 +
  10.547 +static void phys_dev_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
  10.548 +{
  10.549 +    phys_dev_t          *pdev;
  10.550 +    struct task_struct  *p;
  10.551 +    unsigned long cpu_mask = 0;
  10.552 +
  10.553 +    if ( !(pdev = (phys_dev_t *)dev_id) )
  10.554 +    {
  10.555 +        printk("spurious interrupt, no proper device id, %d\n", irq);
  10.556 +        return;
  10.557 +    }
  10.558 +    
  10.559 +    //printk("irq %d pdev=%p\n", irq, pdev);
  10.560 +
  10.561 +    p = pdev->owner;
  10.562 +
  10.563 +    //printk("owner %p\n", p);
  10.564 +
  10.565 +    if ( test_bit(irq, &p->shared_info->virt_phys_irq) )
  10.566 +    {
  10.567 +        printk("irq %d already delivered to guest\n", irq);
  10.568 +        return;
  10.569 +    }
  10.570 +    /* notify guest */
  10.571 +    set_bit(irq, &p->shared_info->virt_phys_irq);
  10.572 +    set_bit(ST_IRQ_DELIVERED, &pdev->state);
  10.573 +    cpu_mask |= mark_guest_event(p, _EVENT_TIMER);
  10.574 +    guest_event_notify(cpu_mask);
  10.575 +}
  10.576 +
  10.577 +/* this is called instead of the PICs original end handler. 
  10.578 + * the real end handler is only called once the guest ack'ed the handling
  10.579 + * of the event. */
  10.580 +static void end_virt_irq (unsigned int i)
  10.581 +{
  10.582 +    /* nothing */
  10.583 +}
  10.584 +
  10.585 +/*
  10.586 + * a guest request an IRQ from a device to be routed to it
  10.587 + * - shared interrupts are not allowed for now
  10.588 + * - we change the hw_irq handler to something else
  10.589 + */
  10.590 +static long pci_request_irq(int irq)
  10.591 +{
  10.592 +    int err;
  10.593 +    phys_dev_t *pdev, *t;
  10.594 +    hw_irq_controller *new, *orig;
  10.595 +    struct list_head *tmp;
  10.596 +
  10.597 +    printk("request irq %d\n", irq);
  10.598 +
  10.599 +    /* find pdev */
  10.600 +
  10.601 +    list_for_each(tmp, &current->dev_list)
  10.602 +    {
  10.603 +        t = list_entry(tmp,  phys_dev_t, node);
  10.604 +        if ( t->dev->irq == irq )
  10.605 +        {
  10.606 +            pdev = t;
  10.607 +            break;
  10.608 +        }
  10.609 +    }
  10.610 +
  10.611 +    if ( !pdev )
  10.612 +    {
  10.613 +        printk("no device matching IRQ %d\n", irq);
  10.614 +        return -EINVAL;
  10.615 +    }
  10.616 +
  10.617 +    printk("pdev= %p\n", pdev);
  10.618 +
  10.619 +    if ( irq >= MAX_IRQS )
  10.620 +    {
  10.621 +        printk("requested IRQ to big %d\n", irq);
  10.622 +        return -EINVAL;
  10.623 +    }
  10.624 +
  10.625 +    if ( irqs[irq] != NULL )
  10.626 +    {
  10.627 +        printk ("irq already in use %d\n", irq);
  10.628 +        return -EPERM;
  10.629 +    }
  10.630 +
  10.631 +    /* allocate a hw_irq controller and copy the original */
  10.632 +    if ( !(new  = kmalloc(sizeof(hw_irq_controller), GFP_KERNEL)) )
  10.633 +    {
  10.634 +        printf("error allocating new irq controller\n");
  10.635 +        return -ENOMEM;
  10.636 +    }
  10.637 +    orig = irq_desc[irq].handler;
  10.638 +    new->typename = orig->typename;
  10.639 +    new->startup = orig->startup;
  10.640 +    new->shutdown = orig->shutdown;
  10.641 +    new->enable = orig->enable;
  10.642 +    new->disable = orig->disable;
  10.643 +    new->ack = orig->ack;
  10.644 +    new->end = orig->end;
  10.645 +    new->set_affinity = orig->set_affinity;
  10.646 +
  10.647 +    /* swap the end routine */
  10.648 +    new->end = end_virt_irq;
  10.649 +
  10.650 +    /* change the irq controllers */
  10.651 +    pdev->orig_handler = orig;
  10.652 +    pdev->new_handler  = new;
  10.653 +    irq_desc[irq].handler = new;
  10.654 +    irqs[irq] = pdev;
  10.655 +    
  10.656 +    printk ("setup handler %d\n", irq);
  10.657 +
  10.658 +    /* request the IRQ. this is not shared! */
  10.659 +    err = request_irq(irq, phys_dev_interrupt, 0, "network", (void *)pdev);
  10.660 +    if ( err )
  10.661 +    {
  10.662 +        printk("error requesting irq\n");
  10.663 +        /* restore original */
  10.664 +        irq_desc[irq].handler = pdev->orig_handler;
  10.665 +        /* free memory */
  10.666 +        kfree(new);
  10.667 +        return err;
  10.668 +    }
  10.669 +
  10.670 +    printk ("done\n");
  10.671 +
  10.672 +    return 0;
  10.673 +}
  10.674 +
  10.675 +static long pci_free_irq(int irq)
  10.676 +{
  10.677 +    /* XXX restore original handler and free_irq() */
  10.678 +    return 0;
  10.679 +}
  10.680 +
  10.681 +static long pci_enable_irq(int irq)
  10.682 +{
  10.683 +    /* XXX not sure we need this */
  10.684 +    /* guest can enable phys_irq event for now */
  10.685 +    return 0;
  10.686 +}
  10.687 +
  10.688 +static long pci_disable_irq(int irq)
  10.689 +{
  10.690 +    /* XXX not sure we need this */
  10.691 +    /* guest can disable phys_irq event for now */
  10.692 +    return 0;
  10.693 +}
  10.694 +
  10.695 +static long pci_finished_irq(int irq)
  10.696 +{
  10.697 +    phys_dev_t *pdev;
  10.698 +    
  10.699 +    if ( !(pdev = irqs[irq]) )
  10.700 +    {
  10.701 +        printk("finished_irq called for unregistered irq %d\n", irq);
  10.702 +        return -EINVAL;
  10.703 +    }
  10.704 +   
  10.705 +    if ( pdev->owner != current )
  10.706 +    {
  10.707 +        printk("finished_irq called dom not owning irq %d\n", irq);
  10.708 +        return -EPERM;
  10.709 +    }
  10.710 +
  10.711 +    if ( !test_bit(ST_IRQ_DELIVERED, &pdev->state) )
  10.712 +    {
  10.713 +        printk("finished_irq called for undelivered irq %d\n", irq);
  10.714 +        return -EINVAL;
  10.715 +    }
  10.716 +
  10.717 +    if ( test_bit(irq, &current->shared_info->virt_phys_irq) )
  10.718 +    {
  10.719 +        printk("finished_irq called for un-acknowleged irq %d\n", irq);        
  10.720 +        return -EINVAL;
  10.721 +    }
  10.722 +
  10.723 +    clear_bit(ST_IRQ_DELIVERED, &pdev->state);
  10.724 +
  10.725 +    /* call original end handler */
  10.726 +    pdev->orig_handler->end(irq);
  10.727 +
  10.728 +    return 0;
  10.729 +}
  10.730 +
  10.731 +/*
  10.732 + * demux hypervisor call.
  10.733 + */
  10.734 +long do_phys_dev_op(phys_dev_op_t *uop)
  10.735 +{
  10.736 +    phys_dev_op_t op;
  10.737 +    long ret;
  10.738 +
  10.739 +
  10.740 +    if ( unlikely(copy_from_user(&op, uop, sizeof(op)) != 0) )
  10.741 +        return -EFAULT;
  10.742 +
  10.743 +    switch ( op.cmd )
  10.744 +    {
  10.745 +    case DEVOP_CFGREG_READ:
  10.746 +        ret = pci_cfgreg_read (op.u.cfg_read.seg, op.u.cfg_read.bus,
  10.747 +                               op.u.cfg_read.dev, op.u.cfg_read.func,
  10.748 +                               op.u.cfg_read.reg, op.u.cfg_read.len,
  10.749 +                               &op.u.cfg_read.value);
  10.750 +        break;
  10.751 +
  10.752 +    case DEVOP_CFGREG_WRITE:
  10.753 +        ret = pci_cfgreg_write (op.u.cfg_write.seg, op.u.cfg_write.bus,
  10.754 +                                op.u.cfg_write.dev, op.u.cfg_write.func,
  10.755 +                                op.u.cfg_write.reg, op.u.cfg_write.len,
  10.756 +                                op.u.cfg_write.value);
  10.757 +        break;
  10.758 +
  10.759 +    case DEVOP_FIND_IRQ:
  10.760 +        ret = pci_find_irq (op.u.find_irq.seg, op.u.find_irq.bus,
  10.761 +                            op.u.find_irq.dev, op.u.find_irq.func,
  10.762 +                            &op.u.find_irq.irq);
  10.763 +        break;
  10.764 +
  10.765 +    case DEVOP_REQUEST_IRQ:
  10.766 +        ret = pci_request_irq (op.u.request_irq.irq);
  10.767 +        break;
  10.768 +
  10.769 +    case DEVOP_FREE_IRQ:
  10.770 +        ret = pci_free_irq (op.u.free_irq.irq);
  10.771 +        break;
  10.772 +
  10.773 +    case DEVOP_ENABLE_IRQ:
  10.774 +        ret = pci_enable_irq (op.u.enable_irq.irq);
  10.775 +        break;
  10.776 +
  10.777 +    case DEVOP_DISABLE_IRQ:
  10.778 +        ret = pci_disable_irq (op.u.disable_irq.irq);
  10.779 +        break;
  10.780 +
  10.781 +    case DEVOP_FINISHED_IRQ:
  10.782 +        ret = pci_finished_irq (op.u.finished_irq.irq);
  10.783 +        break;
  10.784 +
  10.785 +    default:
  10.786 +        ret = -EINVAL;
  10.787 +        break;
  10.788 +    }
  10.789 +
  10.790 +    copy_to_user(uop, &op, sizeof(op));
  10.791 +    return ret;
  10.792 +}
  10.793 +
  10.794 +
  10.795 +/*
  10.796 + * Domain 0 has read access to all devices.
  10.797 + * XXX this is a bit of a hack
  10.798 + */
  10.799 +void physdev_init_dom0(struct task_struct *p)
  10.800 +{
  10.801 +    struct pci_dev *dev;
  10.802 +    phys_dev_t *pdev;
  10.803 +
  10.804 +    printk("Give Dom0 read access to all PCI devices\n");
  10.805 +
  10.806 +    INIT_LIST_HEAD(&p->dev_list);
  10.807 +
  10.808 +    pci_for_each_dev(dev)
  10.809 +    {
  10.810 +        /* add device */
  10.811 +        pdev = kmalloc(sizeof(phys_dev_t), GFP_KERNEL);
  10.812 +        pdev->dev = dev;
  10.813 +        pdev->flags = ACC_READ;
  10.814 +        pdev->state = 0;
  10.815 +        pdev->owner = p;
  10.816 +        list_add(&pdev->node, &p->dev_list);
  10.817 +	}    
  10.818 +}
    11.1 --- a/xen/drivers/char/console.c	Fri Mar 12 13:34:06 2004 +0000
    11.2 +++ b/xen/drivers/char/console.c	Fri Mar 12 13:36:59 2004 +0000
    11.3 @@ -264,7 +264,7 @@ static void serial_rx(unsigned char c, s
    11.4      }
    11.5  }
    11.6  
    11.7 -long do_serial_io(int cmd, int count, char *buffer)
    11.8 +long do_console_io(int cmd, int count, char *buffer)
    11.9  {
   11.10      char *kbuf;
   11.11      long  rc;
   11.12 @@ -275,7 +275,7 @@ long do_serial_io(int cmd, int count, ch
   11.13  
   11.14      switch ( cmd )
   11.15      {
   11.16 -    case SERIALIO_write:
   11.17 +    case CONSOLEIO_write:
   11.18          if ( count > (PAGE_SIZE-1) )
   11.19              count = PAGE_SIZE-1;
   11.20          if ( (kbuf = (char *)get_free_page(GFP_KERNEL)) == NULL )
   11.21 @@ -288,7 +288,7 @@ long do_serial_io(int cmd, int count, ch
   11.22              serial_puts(sercon_handle, kbuf);
   11.23          free_page((unsigned long)kbuf);
   11.24          break;
   11.25 -    case SERIALIO_read:
   11.26 +    case CONSOLEIO_read:
   11.27          rc = 0;
   11.28          while ( (serial_rx_cons != serial_rx_prod) && (rc < count) )
   11.29          {
    12.1 --- a/xen/include/hypervisor-ifs/hypervisor-if.h	Fri Mar 12 13:34:06 2004 +0000
    12.2 +++ b/xen/include/hypervisor-ifs/hypervisor-if.h	Fri Mar 12 13:36:59 2004 +0000
    12.3 @@ -37,7 +37,7 @@
    12.4  #define __HYPERVISOR_set_timer_op         20
    12.5  #define __HYPERVISOR_event_channel_op     21
    12.6  #define __HYPERVISOR_xen_version          22
    12.7 -#define __HYPERVISOR_serial_io            23
    12.8 +#define __HYPERVISOR_console_io           23
    12.9  
   12.10  /*
   12.11   * MULTICALLS
   12.12 @@ -133,10 +133,10 @@
   12.13  #define SCHEDOP_stop            4   /* Stop executing this domain.       */
   12.14  
   12.15  /*
   12.16 - * Commands to HYPERVISOR_serial_io().
   12.17 + * Commands to HYPERVISOR_console_io().
   12.18   */
   12.19 -#define SERIALIO_write          0
   12.20 -#define SERIALIO_read           1
   12.21 +#define CONSOLEIO_write         0
   12.22 +#define CONSOLEIO_read          1
   12.23  
   12.24  #ifndef __ASSEMBLY__
   12.25  
    13.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c	Fri Mar 12 13:34:06 2004 +0000
    13.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c	Fri Mar 12 13:36:59 2004 +0000
    13.3 @@ -79,7 +79,7 @@ static void priv_conwrite(const char *s,
    13.4  
    13.5      while ( count > 0 )
    13.6      {
    13.7 -        if ( (rc = HYPERVISOR_serial_io(SERIALIO_write, count, s)) > 0 )
    13.8 +        if ( (rc = HYPERVISOR_console_io(CONSOLEIO_write, count, s)) > 0 )
    13.9          {
   13.10              count -= rc;
   13.11              s += rc;
   13.12 @@ -174,7 +174,7 @@ static void __do_console_io(void)
   13.13      if ( start_info.flags & SIF_INITDOMAIN )
   13.14      {
   13.15          /* Receive work. */
   13.16 -        while ( (len = HYPERVISOR_serial_io(SERIALIO_read, 16, rbuf)) > 0 )
   13.17 +        while ( (len = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0 )
   13.18              for ( i = 0; i < len; i++ )
   13.19                  tty_insert_flip_char(xeno_console_tty, rbuf[i], 0);
   13.20          if ( xeno_console_tty->flip.count != 0 )
    14.1 --- a/xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h	Fri Mar 12 13:34:06 2004 +0000
    14.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xeno/hypervisor.h	Fri Mar 12 13:36:59 2004 +0000
    14.3 @@ -440,12 +440,12 @@ static inline int HYPERVISOR_xen_version
    14.4      return ret;
    14.5  }
    14.6  
    14.7 -static inline int HYPERVISOR_serial_io(int cmd, int count, char *str)
    14.8 +static inline int HYPERVISOR_console_io(int cmd, int count, char *str)
    14.9  {
   14.10      int ret;
   14.11      __asm__ __volatile__ (
   14.12          TRAP_INSTR
   14.13 -        : "=a" (ret) : "0" (__HYPERVISOR_serial_io),
   14.14 +        : "=a" (ret) : "0" (__HYPERVISOR_console_io),
   14.15          "b" (cmd), "c" (count), "d" (str) : "memory" );
   14.16  
   14.17      return ret;