ia64/xen-unstable

changeset 1327:fcf60f047642

bitkeeper revision 1.879.1.4 (40910c4eH3ROUM3oHZRCARBR6iMt8w)

Updates to PCI virt:
* Add support for hiding devices from dom0
* Don't show bridges to non-0 domains by default.
* Return the standard value of all 1s for config reads to
non-visible devices.
author mwilli2@equilibrium.research.intel-research.net
date Thu Apr 29 14:08:14 2004 +0000 (2004-04-29)
parents 7178b507e88b
children db0162779602
files xen/common/kernel.c xen/common/physdev.c
line diff
     1.1 --- a/xen/common/kernel.c	Wed Apr 28 14:08:16 2004 +0000
     1.2 +++ b/xen/common/kernel.c	Thu Apr 29 14:08:14 2004 +0000
     1.3 @@ -73,6 +73,9 @@ unsigned char opt_pdb[10] = "none";
     1.4  unsigned int opt_tbuf_size = 1;
     1.5  /* opt_sched: scheduler - default to Borrowed Virtual Time */
     1.6  char opt_sched[10] = "bvt";
     1.7 +/* opt_physdev_dom0_hide: list of PCI slots to hide from dom0
     1.8 + * Should have the format '(%02x:%02x.%1x)(%02x:%02x.%1x)...etc' */
     1.9 +char opt_physdev_dom0_hide[20] = "";
    1.10  
    1.11  static struct {
    1.12      unsigned char *name;
    1.13 @@ -94,6 +97,7 @@ static struct {
    1.14      { "pdb",              OPT_STR,  &opt_pdb },
    1.15      { "tbuf_size",        OPT_UINT, &opt_tbuf_size },
    1.16      { "sched",            OPT_STR,  &opt_sched },
    1.17 +    { "physdev_dom0_hide",OPT_STR,  &opt_physdev_dom0_hide },
    1.18      { NULL,               0,        NULL     }
    1.19  };
    1.20  
     2.1 --- a/xen/common/physdev.c	Wed Apr 28 14:08:16 2004 +0000
     2.2 +++ b/xen/common/physdev.c	Thu Apr 29 14:08:14 2004 +0000
     2.3 @@ -115,16 +115,17 @@ static void add_dev_to_task(struct task_
     2.4  
     2.5  /*
     2.6   * physdev_pci_access_modify:
     2.7 - * Allow/disallow access to a specific PCI device. Also allow read access to 
     2.8 - * PCI devices from the device to the root of the device tree. If the given 
     2.9 - * device is a bridge, then the domain should get access to all the devices 
    2.10 - * attached to that bridge (XXX this is unimplemented!).
    2.11 + * Allow/disallow access to a specific PCI device.  Guests should not be
    2.12 + * allowed to see bridge devices as it needlessly complicates things (one
    2.13 + * possible exception to this is the AGP bridge).  If the given device is a
    2.14 + * bridge, then the domain should get access to all the leaf devices below
    2.15 + * that bridge (XXX this is unimplemented!).
    2.16   */
    2.17  int physdev_pci_access_modify(
    2.18      domid_t dom, int bus, int dev, int func, int enable)
    2.19  {
    2.20      struct task_struct *p;
    2.21 -    struct pci_dev *pdev, *rdev, *tdev;
    2.22 +    struct pci_dev *pdev;
    2.23      int rc = 0;
    2.24   
    2.25      if ( !IS_PRIV(current) )
    2.26 @@ -145,7 +146,7 @@ int physdev_pci_access_modify(
    2.27          return -ESRCH;
    2.28  
    2.29      /* Make the domain privileged. */
    2.30 -    set_bit(PF_PRIVILEGED, &p->flags); 
    2.31 +    set_bit(PF_PRIVILEGED, &p->flags);
    2.32  
    2.33      /* Grant write access to the specified device. */
    2.34      if ( (pdev = pci_find_slot(bus, PCI_DEVFN(dev, func))) == NULL )
    2.35 @@ -155,27 +156,10 @@ int physdev_pci_access_modify(
    2.36          goto out;
    2.37      }
    2.38      add_dev_to_task(p, pdev, ACC_WRITE);
    2.39 +
    2.40      INFO("  add RW %02x:%02x:%02x\n", pdev->bus->number,
    2.41           PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
    2.42  
    2.43 -    /* Grant read access to the root device. */
    2.44 -    if ( (rdev = pci_find_slot(0, PCI_DEVFN(0, 0))) == NULL )
    2.45 -    {
    2.46 -        INFO("  bizarre -- no PCI root dev\n");
    2.47 -        rc = -ENODEV;
    2.48 -        goto out;
    2.49 -    }
    2.50 -    add_dev_to_task(p, rdev, ACC_READ);
    2.51 -    INFO("  add R0 %02x:%02x:%02x\n", 0, 0, 0);
    2.52 -
    2.53 -    /* Grant read access to all devices on the path to the root. */
    2.54 -    for ( tdev = pdev->bus->self; tdev != NULL; tdev = tdev->bus->self )
    2.55 -    {
    2.56 -        add_dev_to_task(p, tdev, ACC_READ);
    2.57 -        INFO("  add RO %02x:%02x:%02x\n", tdev->bus->number,
    2.58 -             PCI_SLOT(tdev->devfn), PCI_FUNC(tdev->devfn));
    2.59 -    }
    2.60 -
    2.61      /* Is the device a bridge or cardbus? */
    2.62      if ( pdev->hdr_type != PCI_HEADER_TYPE_NORMAL )
    2.63          INFO("XXX can't give access to bridge devices yet\n");
    2.64 @@ -256,8 +240,16 @@ static int do_base_address_access(phys_d
    2.65  
    2.66      if ( len != sizeof(u32) )
    2.67      {
    2.68 -        INFO("Guest attempting sub-dword %s to BASE_ADDRESS %d\n", 
    2.69 +        /* This isn't illegal, but there doesn't seem to be a very good reason
    2.70 +         * to do it for normal devices (bridges are another matter).  Since it
    2.71 +         * would complicate the code below, we don't support this for now. */
    2.72 +
    2.73 +        /* We could set *val to some value but the guest may well be in trouble
    2.74 +         * anyway if this write fails.  Hopefully the printk will give us a
    2.75 +         * clue what went wrong. */
    2.76 +        printk("Guest attempting sub-dword %s to BASE_ADDRESS %d\n", 
    2.77               (acc == ACC_READ) ? "read" : "write", idx);
    2.78 +        
    2.79          return -EPERM;
    2.80      }
    2.81  
    2.82 @@ -420,7 +412,13 @@ static long pci_cfgreg_read(int bus, int
    2.83      phys_dev_t *pdev;
    2.84  
    2.85      if ( (ret = check_dev_acc(current, bus, dev, func, &pdev)) != 0 )
    2.86 -        return ret;
    2.87 +    {
    2.88 +        /* PCI spec states that reads from non-existent devices should return
    2.89 +         * all 1s.  In this case the domain has no read access, which should
    2.90 +         * also look like the device is non-existent. */
    2.91 +        *val = 0xFFFFFFFF;
    2.92 +        return 0;
    2.93 +    }
    2.94  
    2.95      /* Fake out read requests for some registers. */
    2.96      switch ( reg )
    2.97 @@ -608,6 +606,21 @@ long do_physdev_op(physdev_op_t *uop)
    2.98      return ret;
    2.99  }
   2.100  
   2.101 +/* Test if boot params specify this device should NOT be visible to DOM0
   2.102 + * (e.g. so that another domain can control it instead) */
   2.103 +int pcidev_dom0_hidden(struct pci_dev *dev)
   2.104 +{
   2.105 +    extern char opt_physdev_dom0_hide[];
   2.106 +    char cmp[10] = "(.......)";
   2.107 +    
   2.108 +    strncpy(&cmp[1], dev->slot_name, 7);
   2.109 +
   2.110 +    if ( strstr(opt_physdev_dom0_hide, dev->slot_name) == NULL )
   2.111 +        return 0;
   2.112 +    
   2.113 +    return 1;
   2.114 +}
   2.115 +
   2.116  
   2.117  /* Domain 0 has read access to all devices. */
   2.118  void physdev_init_dom0(struct task_struct *p)
   2.119 @@ -619,14 +632,24 @@ void physdev_init_dom0(struct task_struc
   2.120  
   2.121      pci_for_each_dev(dev)
   2.122      {
   2.123 -        /* Skip bridges and other peculiarities for now. */
   2.124 -        if ( dev->hdr_type != PCI_HEADER_TYPE_NORMAL )
   2.125 -            continue;
   2.126 -        pdev = kmalloc(sizeof(phys_dev_t), GFP_KERNEL);
   2.127 -        pdev->dev = dev;
   2.128 -        pdev->flags = ACC_WRITE;
   2.129 -        pdev->state = 0;
   2.130 -        pdev->owner = p;
   2.131 -        list_add(&pdev->node, &p->pcidev_list);
   2.132 -	}    
   2.133 +        if ( !pcidev_dom0_hidden(dev) )
   2.134 +        {            
   2.135 +            /* Skip bridges and other peculiarities for now. */
   2.136 +            if ( dev->hdr_type != PCI_HEADER_TYPE_NORMAL )
   2.137 +                continue;
   2.138 +            
   2.139 +            pdev = kmalloc(sizeof(phys_dev_t), GFP_KERNEL);
   2.140 +            pdev->dev = dev;
   2.141 +            pdev->flags = ACC_WRITE;
   2.142 +            pdev->state = 0;
   2.143 +            pdev->owner = p;
   2.144 +            list_add(&pdev->node, &p->pcidev_list);
   2.145 +        }
   2.146 +        else
   2.147 +        {
   2.148 +            printk("Hiding PCI device %s from DOM0\n",
   2.149 +                   dev->slot_name);
   2.150 +        }
   2.151 +    }
   2.152  }
   2.153 +