ia64/xen-unstable

changeset 8468:d966b7a00959

Allow non-privileged domains restricted access to
I/O memory and physical interrupts, under control
of domain0. Capabilities are maintained as rangesets
in Xen.

Signed-off-by: Ryan Wilson <hap9@epoch.ncsc.mil>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Dec 31 14:15:22 2005 +0100 (2005-12-31)
parents 4369fd869f51
children 364128d29f4e
files tools/libxc/xc_domain.c tools/libxc/xenctrl.h tools/python/xen/lowlevel/xc/xc.c xen/arch/ia64/xen/domain.c xen/arch/ia64/xen/irq.c xen/arch/x86/dom0_ops.c xen/arch/x86/domain_build.c xen/arch/x86/irq.c xen/arch/x86/mm.c xen/arch/x86/physdev.c xen/arch/x86/traps.c xen/common/dom0_ops.c xen/common/domain.c xen/common/event_channel.c xen/common/memory.c xen/common/rangeset.c xen/drivers/char/ns16550.c xen/include/asm-x86/iocap.h xen/include/public/dom0_ops.h xen/include/xen/compiler.h xen/include/xen/iocap.h xen/include/xen/rangeset.h xen/include/xen/sched.h
line diff
     1.1 --- a/tools/libxc/xc_domain.c	Sat Dec 31 13:11:47 2005 +0100
     1.2 +++ b/tools/libxc/xc_domain.c	Sat Dec 31 14:15:22 2005 +0100
     1.3 @@ -404,6 +404,38 @@ int xc_domain_setinfo(int xc_handle,
     1.4  
     1.5  }
     1.6  
     1.7 +int xc_domain_irq_permission(int xc_handle,
     1.8 +                             uint32_t domid,
     1.9 +                             uint8_t pirq,
    1.10 +                             uint8_t allow_access)
    1.11 +{
    1.12 +    dom0_op_t op;
    1.13 +
    1.14 +    op.cmd = DOM0_IRQ_PERMISSION;
    1.15 +    op.u.irq_permission.domain = domid;
    1.16 +    op.u.irq_permission.pirq = pirq;
    1.17 +    op.u.irq_permission.allow_access = allow_access;
    1.18 +
    1.19 +    return do_dom0_op(xc_handle, &op);
    1.20 +}
    1.21 +
    1.22 +int xc_domain_iomem_permission(int xc_handle,
    1.23 +                               uint32_t domid,
    1.24 +                               unsigned long first_pfn,
    1.25 +                               unsigned long nr_pfns,
    1.26 +                               uint8_t allow_access)
    1.27 +{
    1.28 +    dom0_op_t op;
    1.29 +
    1.30 +    op.cmd = DOM0_IOMEM_PERMISSION;
    1.31 +    op.u.iomem_permission.domain = domid;
    1.32 +    op.u.iomem_permission.first_pfn = first_pfn;
    1.33 +	op.u.iomem_permission.nr_pfns = nr_pfns;
    1.34 +    op.u.iomem_permission.allow_access = allow_access;
    1.35 +
    1.36 +    return do_dom0_op(xc_handle, &op);
    1.37 +}
    1.38 +
    1.39  /*
    1.40   * Local variables:
    1.41   * mode: C
     2.1 --- a/tools/libxc/xenctrl.h	Sat Dec 31 13:11:47 2005 +0100
     2.2 +++ b/tools/libxc/xenctrl.h	Sat Dec 31 14:15:22 2005 +0100
     2.3 @@ -380,6 +380,17 @@ int xc_domain_ioport_permission(int xc_h
     2.4                                  uint32_t nr_ports,
     2.5                                  uint32_t allow_access);
     2.6  
     2.7 +int xc_domain_irq_permission(int xc_handle,
     2.8 +                             uint32_t domid,
     2.9 +                             uint8_t pirq,
    2.10 +                             uint8_t allow_access);
    2.11 +
    2.12 +int xc_domain_iomem_permission(int xc_handle,
    2.13 +                               uint32_t domid,
    2.14 +                               unsigned long first_pfn,
    2.15 +                               unsigned long nr_pfns,
    2.16 +                               uint8_t allow_access);
    2.17 +
    2.18  unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid, 
    2.19  				    unsigned long mfn);
    2.20  
     3.1 --- a/tools/python/xen/lowlevel/xc/xc.c	Sat Dec 31 13:11:47 2005 +0100
     3.2 +++ b/tools/python/xen/lowlevel/xc/xc.c	Sat Dec 31 14:15:22 2005 +0100
     3.3 @@ -774,6 +774,52 @@ static PyObject *pyxc_domain_ioport_perm
     3.4      return zero;
     3.5  }
     3.6  
     3.7 +static PyObject *pyxc_domain_irq_permission(PyObject *self,
     3.8 +                                            PyObject *args,
     3.9 +                                            PyObject *kwds)
    3.10 +{
    3.11 +    XcObject *xc = (XcObject *)self;
    3.12 +    uint32_t dom;
    3.13 +    int pirq, allow_access, ret;
    3.14 +
    3.15 +    static char *kwd_list[] = { "dom", "pirq", "allow_access", NULL };
    3.16 +
    3.17 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list, 
    3.18 +                                      &dom, &pirq, &allow_access) )
    3.19 +        return NULL;
    3.20 +
    3.21 +    ret = xc_domain_irq_permission(
    3.22 +        xc->xc_handle, dom, pirq, allow_access);
    3.23 +    if ( ret != 0 )
    3.24 +        return PyErr_SetFromErrno(xc_error);
    3.25 +
    3.26 +    Py_INCREF(zero);
    3.27 +    return zero;
    3.28 +}
    3.29 +
    3.30 +static PyObject *pyxc_domain_iomem_permission(PyObject *self,
    3.31 +                                               PyObject *args,
    3.32 +                                               PyObject *kwds)
    3.33 +{
    3.34 +    XcObject *xc = (XcObject *)self;
    3.35 +    uint32_t dom;
    3.36 +    unsigned long first_pfn, nr_pfns, allow_access, ret;
    3.37 +
    3.38 +    static char *kwd_list[] = { "dom", "first_pfn", "nr_pfns", "allow_access", NULL };
    3.39 +
    3.40 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illi", kwd_list, 
    3.41 +                                      &dom, &first_pfn, &nr_pfns, &allow_access) )
    3.42 +        return NULL;
    3.43 +
    3.44 +    ret = xc_domain_iomem_permission(
    3.45 +        xc->xc_handle, dom, first_pfn, nr_pfns, allow_access);
    3.46 +    if ( ret != 0 )
    3.47 +        return PyErr_SetFromErrno(xc_error);
    3.48 +
    3.49 +    Py_INCREF(zero);
    3.50 +    return zero;
    3.51 +}
    3.52 +
    3.53  
    3.54  static PyObject *dom_op(XcObject *self, PyObject *args,
    3.55                          int (*fn)(int, uint32_t))
    3.56 @@ -1070,6 +1116,25 @@ static PyMethodDef pyxc_methods[] = {
    3.57        " allow_access [int]: Non-zero means enable access; else disable access\n\n"
    3.58        "Returns: [int] 0 on success; -1 on error.\n" },
    3.59  
    3.60 +    { "domain_irq_permission",
    3.61 +      (PyCFunction)pyxc_domain_irq_permission,
    3.62 +      METH_VARARGS | METH_KEYWORDS, "\n"
    3.63 +      "Allow a domain access to a physical IRQ\n"
    3.64 +      " dom          [int]: Identifier of domain to be allowed access.\n"
    3.65 +      " pirq         [int]: The Physical IRQ\n"
    3.66 +      " allow_access [int]: Non-zero means enable access; else disable access\n\n"
    3.67 +      "Returns: [int] 0 on success; -1 on error.\n" },
    3.68 +
    3.69 +    { "domain_iomem_permission",
    3.70 +      (PyCFunction)pyxc_domain_iomem_permission,
    3.71 +      METH_VARARGS | METH_KEYWORDS, "\n"
    3.72 +      "Allow a domain access to a range of IO memory pages\n"
    3.73 +      " dom          [int]: Identifier of domain to be allowed access.\n"
    3.74 +      " first_pfn   [long]: First page of I/O Memory\n"
    3.75 +      " nr_pfns     [long]: Number of pages of I/O Memory (>0)\n"
    3.76 +      " allow_access [int]: Non-zero means enable access; else disable access\n\n"
    3.77 +      "Returns: [int] 0 on success; -1 on error.\n" },
    3.78 +
    3.79      { "pages_to_kib",
    3.80        (PyCFunction)pyxc_pages_to_kib,
    3.81        METH_VARARGS, "\n"
     4.1 --- a/xen/arch/ia64/xen/domain.c	Sat Dec 31 13:11:47 2005 +0100
     4.2 +++ b/xen/arch/ia64/xen/domain.c	Sat Dec 31 14:15:22 2005 +0100
     4.3 @@ -765,7 +765,10 @@ void alloc_dom0(void)
     4.4   */
     4.5  void physdev_init_dom0(struct domain *d)
     4.6  {
     4.7 -	set_bit(_DOMF_physdev_access, &d->domain_flags);
     4.8 +	if (iomem_permit_access(d, 0UL, ~0UL))
     4.9 +		BUG();
    4.10 +	if (irqs_permit_access(d, 0, NR_PIRQS-1))
    4.11 +		BUG();
    4.12  }
    4.13  
    4.14  unsigned int vmx_dom0 = 0;
     5.1 --- a/xen/arch/ia64/xen/irq.c	Sat Dec 31 13:11:47 2005 +0100
     5.2 +++ b/xen/arch/ia64/xen/irq.c	Sat Dec 31 14:15:22 2005 +0100
     5.3 @@ -1378,9 +1378,6 @@ int pirq_guest_bind(struct vcpu *d, int 
     5.4      unsigned long       flags;
     5.5      int                 rc = 0;
     5.6  
     5.7 -    if ( !IS_CAPABLE_PHYSDEV(d->domain) )
     5.8 -        return -EPERM;
     5.9 -
    5.10      spin_lock_irqsave(&desc->lock, flags);
    5.11  
    5.12      action = (irq_guest_action_t *)desc->action;
     6.1 --- a/xen/arch/x86/dom0_ops.c	Sat Dec 31 13:11:47 2005 +0100
     6.2 +++ b/xen/arch/x86/dom0_ops.c	Sat Dec 31 14:15:22 2005 +0100
     6.3 @@ -152,14 +152,12 @@ long arch_do_dom0_op(dom0_op_t *op, dom0
     6.4              op->u.ioport_permission.domain)) == NULL) )
     6.5              break;
     6.6  
     6.7 -        ret = 0;
     6.8 -        if ( np > 0 )
     6.9 -        {
    6.10 -            if ( op->u.ioport_permission.allow_access )
    6.11 -                ioport_range_permit(d, fp, fp + np - 1);
    6.12 -            else
    6.13 -                ioport_range_deny(d, fp, fp + np - 1);
    6.14 -        }
    6.15 +        if ( np == 0 )
    6.16 +            ret = 0;
    6.17 +        else if ( op->u.ioport_permission.allow_access )
    6.18 +            ret = ioports_permit_access(d, fp, fp + np - 1);
    6.19 +        else
    6.20 +            ret = ioports_deny_access(d, fp, fp + np - 1);
    6.21  
    6.22          put_domain(d);
    6.23      }
     7.1 --- a/xen/arch/x86/domain_build.c	Sat Dec 31 13:11:47 2005 +0100
     7.2 +++ b/xen/arch/x86/domain_build.c	Sat Dec 31 14:15:22 2005 +0100
     7.3 @@ -94,7 +94,7 @@ static struct pfn_info *alloc_chunk(stru
     7.4      return page;
     7.5  }
     7.6  
     7.7 -static void process_dom0_ioports_disable()
     7.8 +static void process_dom0_ioports_disable(void)
     7.9  {
    7.10      unsigned long io_from, io_to;
    7.11      char *t, *u, *s = opt_dom0_ioports_disable;
    7.12 @@ -126,7 +126,8 @@ static void process_dom0_ioports_disable
    7.13          printk("Disabling dom0 access to ioport range %04lx-%04lx\n",
    7.14              io_from, io_to);
    7.15  
    7.16 -        ioport_range_deny(dom0, io_from, io_to);
    7.17 +        if ( ioports_deny_access(dom0, io_from, io_to) != 0 )
    7.18 +            BUG();
    7.19      }
    7.20  }
    7.21  
    7.22 @@ -741,24 +742,29 @@ int construct_dom0(struct domain *d,
    7.23          printk("dom0: shadow setup done\n");
    7.24      }
    7.25  
    7.26 +    i = 0;
    7.27 +
    7.28      /* DOM0 is permitted full I/O capabilities. */
    7.29 -    ioport_range_permit(dom0, 0, 0xFFFF);
    7.30 -    set_bit(_DOMF_physdev_access, &dom0->domain_flags);
    7.31 +    i |= ioports_permit_access(dom0, 0, 0xFFFF);
    7.32 +    i |= iomem_permit_access(dom0, 0UL, ~0UL);
    7.33 +    i |= irqs_permit_access(dom0, 0, NR_PIRQS-1);
    7.34  
    7.35      /*
    7.36       * Modify I/O port access permissions.
    7.37       */
    7.38      /* Master Interrupt Controller (PIC). */
    7.39 -    ioport_range_deny(dom0, 0x20, 0x21);
    7.40 +    i |= ioports_deny_access(dom0, 0x20, 0x21);
    7.41      /* Slave Interrupt Controller (PIC). */
    7.42 -    ioport_range_deny(dom0, 0xA0, 0xA1);
    7.43 +    i |= ioports_deny_access(dom0, 0xA0, 0xA1);
    7.44      /* Interval Timer (PIT). */
    7.45 -    ioport_range_deny(dom0, 0x40, 0x43);
    7.46 +    i |= ioports_deny_access(dom0, 0x40, 0x43);
    7.47      /* PIT Channel 2 / PC Speaker Control. */
    7.48 -    ioport_range_deny(dom0, 0x61, 0x61);
    7.49 +    i |= ioports_deny_access(dom0, 0x61, 0x61);
    7.50      /* Command-line I/O ranges. */
    7.51      process_dom0_ioports_disable();
    7.52  
    7.53 +    BUG_ON(i != 0);
    7.54 +
    7.55      return 0;
    7.56  }
    7.57  
     8.1 --- a/xen/arch/x86/irq.c	Sat Dec 31 13:11:47 2005 +0100
     8.2 +++ b/xen/arch/x86/irq.c	Sat Dec 31 14:15:22 2005 +0100
     8.3 @@ -199,16 +199,12 @@ int pirq_guest_unmask(struct domain *d)
     8.4  int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
     8.5  {
     8.6      unsigned int        vector = irq_to_vector(irq);
     8.7 -    struct domain      *d = v->domain;
     8.8      irq_desc_t         *desc = &irq_desc[vector];
     8.9      irq_guest_action_t *action;
    8.10      unsigned long       flags;
    8.11      int                 rc = 0;
    8.12      cpumask_t           cpumask = CPU_MASK_NONE;
    8.13  
    8.14 -    if ( !IS_CAPABLE_PHYSDEV(d) )
    8.15 -        return -EPERM;
    8.16 -
    8.17      if ( vector == 0 )
    8.18          return -EBUSY;
    8.19  
     9.1 --- a/xen/arch/x86/mm.c	Sat Dec 31 13:11:47 2005 +0100
     9.2 +++ b/xen/arch/x86/mm.c	Sat Dec 31 14:15:22 2005 +0100
     9.3 @@ -96,6 +96,7 @@
     9.4  #include <xen/softirq.h>
     9.5  #include <xen/domain_page.h>
     9.6  #include <xen/event.h>
     9.7 +#include <xen/iocap.h>
     9.8  #include <asm/shadow.h>
     9.9  #include <asm/page.h>
    9.10  #include <asm/flushtlb.h>
    9.11 @@ -437,7 +438,6 @@ get_page_from_l1e(
    9.12      unsigned long mfn = l1e_get_pfn(l1e);
    9.13      struct pfn_info *page = pfn_to_page(mfn);
    9.14      int okay;
    9.15 -    extern int domain_iomem_in_pfn(struct domain *d, unsigned long pfn);
    9.16  
    9.17      if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
    9.18          return 1;
    9.19 @@ -455,8 +455,7 @@ get_page_from_l1e(
    9.20          if ( d == dom_io )
    9.21              d = current->domain;
    9.22  
    9.23 -        if ( (!IS_PRIV(d)) &&
    9.24 -             (!IS_CAPABLE_PHYSDEV(d) || !domain_iomem_in_pfn(d, mfn)) )
    9.25 +        if ( !iomem_access_permitted(d, mfn, mfn) )
    9.26          {
    9.27              MEM_LOG("Non-privileged attempt to map I/O space %08lx", mfn);
    9.28              return 0;
    9.29 @@ -1887,7 +1886,7 @@ int do_mmuext_op(
    9.30              break;
    9.31  
    9.32          case MMUEXT_FLUSH_CACHE:
    9.33 -            if ( unlikely(!IS_CAPABLE_PHYSDEV(d)) )
    9.34 +            if ( unlikely(!cache_flush_permitted(d)) )
    9.35              {
    9.36                  MEM_LOG("Non-physdev domain tried to FLUSH_CACHE.");
    9.37                  okay = 0;
    10.1 --- a/xen/arch/x86/physdev.c	Sat Dec 31 13:11:47 2005 +0100
    10.2 +++ b/xen/arch/x86/physdev.c	Sat Dec 31 14:15:22 2005 +0100
    10.3 @@ -14,13 +14,6 @@
    10.4  extern int ioapic_guest_read(int apicid, int address, u32 *pval);
    10.5  extern int ioapic_guest_write(int apicid, int address, u32 pval);
    10.6  
    10.7 -/* Check if a domain controls a device with IO memory within frame @pfn.
    10.8 - * Returns: 1 if the domain should be allowed to map @pfn, 0 otherwise.  */
    10.9 -int domain_iomem_in_pfn(struct domain *p, unsigned long pfn)
   10.10 -{
   10.11 -    return 0;
   10.12 -}
   10.13 -
   10.14  /*
   10.15   * Demuxing hypercall.
   10.16   */
    11.1 --- a/xen/arch/x86/traps.c	Sat Dec 31 13:11:47 2005 +0100
    11.2 +++ b/xen/arch/x86/traps.c	Sat Dec 31 14:15:22 2005 +0100
    11.3 @@ -623,7 +623,7 @@ static inline int admin_io_okay(
    11.4      unsigned int port, unsigned int bytes,
    11.5      struct vcpu *v, struct cpu_user_regs *regs)
    11.6  {
    11.7 -    return ioport_range_access_permitted(v->domain, port, port + bytes - 1);
    11.8 +    return ioports_access_permitted(v->domain, port, port + bytes - 1);
    11.9  }
   11.10  
   11.11  /* Check admin limits. Silently fail the access if it is disallowed. */
   11.12 @@ -863,7 +863,7 @@ static int emulate_privileged_op(struct 
   11.13  
   11.14      case 0x09: /* WBINVD */
   11.15          /* Ignore the instruction if unprivileged. */
   11.16 -        if ( !IS_CAPABLE_PHYSDEV(v->domain) )
   11.17 +        if ( !cache_flush_permitted(v->domain) )
   11.18              DPRINTK("Non-physdev domain attempted WBINVD.\n");
   11.19          else
   11.20              wbinvd();
    12.1 --- a/xen/common/dom0_ops.c	Sat Dec 31 13:11:47 2005 +0100
    12.2 +++ b/xen/common/dom0_ops.c	Sat Dec 31 14:15:22 2005 +0100
    12.3 @@ -16,6 +16,7 @@
    12.4  #include <xen/domain_page.h>
    12.5  #include <xen/trace.h>
    12.6  #include <xen/console.h>
    12.7 +#include <xen/iocap.h>
    12.8  #include <asm/current.h>
    12.9  #include <public/dom0_ops.h>
   12.10  #include <public/sched_ctl.h>
   12.11 @@ -582,6 +583,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   12.12          }
   12.13      }
   12.14      break;
   12.15 +
   12.16      case DOM0_SETDEBUGGING:
   12.17      {
   12.18          struct domain *d; 
   12.19 @@ -599,6 +601,53 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
   12.20      }
   12.21      break;
   12.22  
   12.23 +    case DOM0_IRQ_PERMISSION:
   12.24 +    {
   12.25 +        struct domain *d;
   12.26 +        unsigned int pirq = op->u.irq_permission.pirq;
   12.27 +
   12.28 +        ret = -EINVAL;
   12.29 +        if ( pirq >= NR_PIRQS )
   12.30 +            break;
   12.31 +
   12.32 +        ret = -ESRCH;
   12.33 +        d = find_domain_by_id(op->u.irq_permission.domain);
   12.34 +        if ( d == NULL )
   12.35 +            break;
   12.36 +
   12.37 +        if ( op->u.irq_permission.allow_access )
   12.38 +            ret = irq_permit_access(d, pirq);
   12.39 +        else
   12.40 +            ret = irq_deny_access(d, pirq);
   12.41 +
   12.42 +        put_domain(d);
   12.43 +    }
   12.44 +    break;
   12.45 +
   12.46 +    case DOM0_IOMEM_PERMISSION:
   12.47 +    {
   12.48 +        struct domain *d;
   12.49 +        unsigned long pfn = op->u.iomem_permission.first_pfn;
   12.50 +        unsigned long nr_pfns = op->u.iomem_permission.nr_pfns;
   12.51 +
   12.52 +        ret = -EINVAL;
   12.53 +        if ( (pfn + nr_pfns - 1) < pfn ) /* wrap? */
   12.54 +            break;
   12.55 +
   12.56 +        ret = -ESRCH;
   12.57 +        d = find_domain_by_id(op->u.iomem_permission.domain);
   12.58 +        if ( d == NULL )
   12.59 +            break;
   12.60 +
   12.61 +        if ( op->u.iomem_permission.allow_access )
   12.62 +            ret = iomem_permit_access(d, pfn, pfn + nr_pfns - 1);
   12.63 +        else
   12.64 +            ret = iomem_deny_access(d, pfn, pfn + nr_pfns - 1);
   12.65 +
   12.66 +        put_domain(d);
   12.67 +    }
   12.68 +    break;
   12.69 +
   12.70  #ifdef PERF_COUNTERS
   12.71      case DOM0_PERFCCONTROL:
   12.72      {
    13.1 --- a/xen/common/domain.c	Sat Dec 31 13:11:47 2005 +0100
    13.2 +++ b/xen/common/domain.c	Sat Dec 31 14:15:22 2005 +0100
    13.3 @@ -60,7 +60,12 @@ struct domain *do_createdomain(domid_t d
    13.4  
    13.5      rangeset_domain_initialise(d);
    13.6  
    13.7 -    if ( arch_do_createdomain(v) != 0 )
    13.8 +    d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex);
    13.9 +    d->irq_caps   = rangeset_new(d, "Interrupts", 0);
   13.10 +
   13.11 +    if ( (d->iomem_caps == NULL) ||
   13.12 +         (d->irq_caps == NULL) ||
   13.13 +         (arch_do_createdomain(v) != 0) )
   13.14          goto fail3;
   13.15  
   13.16      if ( !is_idle_task(d) )
    14.1 --- a/xen/common/event_channel.c	Sat Dec 31 13:11:47 2005 +0100
    14.2 +++ b/xen/common/event_channel.c	Sat Dec 31 14:15:22 2005 +0100
    14.3 @@ -22,6 +22,7 @@
    14.4  #include <xen/sched.h>
    14.5  #include <xen/event.h>
    14.6  #include <xen/irq.h>
    14.7 +#include <xen/iocap.h>
    14.8  #include <asm/current.h>
    14.9  
   14.10  #include <public/xen.h>
   14.11 @@ -242,6 +243,9 @@ static long evtchn_bind_pirq(evtchn_bind
   14.12      if ( pirq >= ARRAY_SIZE(d->pirq_to_evtchn) )
   14.13          return -EINVAL;
   14.14  
   14.15 +    if ( !irq_access_permitted(d, pirq) )
   14.16 +        return -EPERM;
   14.17 +
   14.18      spin_lock(&d->evtchn_lock);
   14.19  
   14.20      if ( d->pirq_to_evtchn[pirq] != 0 )
    15.1 --- a/xen/common/memory.c	Sat Dec 31 13:11:47 2005 +0100
    15.2 +++ b/xen/common/memory.c	Sat Dec 31 14:15:22 2005 +0100
    15.3 @@ -15,6 +15,7 @@
    15.4  #include <xen/sched.h>
    15.5  #include <xen/event.h>
    15.6  #include <xen/shadow.h>
    15.7 +#include <xen/iocap.h>
    15.8  #include <asm/current.h>
    15.9  #include <asm/hardirq.h>
   15.10  #include <public/memory.h>
   15.11 @@ -35,7 +36,8 @@ increase_reservation(
   15.12           !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
   15.13          return 0;
   15.14  
   15.15 -    if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
   15.16 +    if ( (extent_order != 0) &&
   15.17 +         !multipage_allocation_permitted(current->domain) )
   15.18      {
   15.19          DPRINTK("Only I/O-capable domains may allocate multi-page extents.\n");
   15.20          return 0;
    16.1 --- a/xen/common/rangeset.c	Sat Dec 31 13:11:47 2005 +0100
    16.2 +++ b/xen/common/rangeset.c	Sat Dec 31 14:15:22 2005 +0100
    16.3 @@ -253,6 +253,12 @@ int rangeset_contains_singleton(
    16.4      return rangeset_contains_range(r, s, s);
    16.5  }
    16.6  
    16.7 +int rangeset_is_empty(
    16.8 +    struct rangeset *r)
    16.9 +{
   16.10 +    return list_empty(&r->range_list);
   16.11 +}
   16.12 +
   16.13  struct rangeset *rangeset_new(
   16.14      struct domain *d, char *name, unsigned int flags)
   16.15  {
    17.1 --- a/xen/drivers/char/ns16550.c	Sat Dec 31 13:11:47 2005 +0100
    17.2 +++ b/xen/drivers/char/ns16550.c	Sat Dec 31 14:15:22 2005 +0100
    17.3 @@ -237,7 +237,8 @@ static void ns16550_init_postirq(struct 
    17.4  static void ns16550_endboot(struct serial_port *port)
    17.5  {
    17.6      struct ns16550 *uart = port->uart;
    17.7 -    ioport_range_deny(dom0, uart->io_base, uart->io_base + 7);
    17.8 +    if ( ioports_deny_access(dom0, uart->io_base, uart->io_base + 7) != 0 )
    17.9 +        BUG();
   17.10  }
   17.11  #else
   17.12  #define ns16550_endboot NULL
    18.1 --- a/xen/include/asm-x86/iocap.h	Sat Dec 31 13:11:47 2005 +0100
    18.2 +++ b/xen/include/asm-x86/iocap.h	Sat Dec 31 14:15:22 2005 +0100
    18.3 @@ -7,11 +7,14 @@
    18.4  #ifndef __X86_IOCAP_H__
    18.5  #define __X86_IOCAP_H__
    18.6  
    18.7 -#define ioport_range_permit(d, s, e)                    \
    18.8 +#define ioports_permit_access(d, s, e)                  \
    18.9      rangeset_add_range((d)->arch.ioport_caps, s, e)
   18.10 -#define ioport_range_deny(d, s, e)                      \
   18.11 +#define ioports_deny_access(d, s, e)                    \
   18.12      rangeset_remove_range((d)->arch.ioport_caps, s, e)
   18.13 -#define ioport_range_access_permitted(d, s, e)          \
   18.14 +#define ioports_access_permitted(d, s, e)               \
   18.15      rangeset_contains_range((d)->arch.ioport_caps, s, e)
   18.16  
   18.17 +#define cache_flush_permitted(d)                       \
   18.18 +    (!rangeset_is_empty((d)->iomem_caps))
   18.19 +
   18.20  #endif /* __X86_IOCAP_H__ */
    19.1 --- a/xen/include/public/dom0_ops.h	Sat Dec 31 13:11:47 2005 +0100
    19.2 +++ b/xen/include/public/dom0_ops.h	Sat Dec 31 14:15:22 2005 +0100
    19.3 @@ -410,6 +410,21 @@ typedef struct {
    19.4      uint8_t enable;
    19.5  } dom0_setdebugging_t;
    19.6  
    19.7 +#define DOM0_IRQ_PERMISSION 46
    19.8 +typedef struct {
    19.9 +    domid_t domain;          /* domain to be affected */
   19.10 +    uint8_t pirq;
   19.11 +    uint8_t allow_access;    /* flag to specify enable/disable of IRQ access */
   19.12 +} dom0_irq_permission_t;
   19.13 +
   19.14 +#define DOM0_IOMEM_PERMISSION 47
   19.15 +typedef struct {
   19.16 +    domid_t  domain;          /* domain to be affected */
   19.17 +    unsigned long first_pfn;  /* first page (physical page number) in range */
   19.18 +    unsigned long nr_pfns;    /* number of pages in range (>0) */
   19.19 +    uint8_t allow_access;     /* allow (!0) or deny (0) access to range? */
   19.20 +} dom0_iomem_permission_t;
   19.21 + 
   19.22  typedef struct {
   19.23      uint32_t cmd;
   19.24      uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
   19.25 @@ -448,6 +463,8 @@ typedef struct {
   19.26          dom0_max_vcpus_t         max_vcpus;
   19.27          dom0_setdomainhandle_t   setdomainhandle;        
   19.28          dom0_setdebugging_t      setdebugging;
   19.29 +        dom0_irq_permission_t    irq_permission;
   19.30 +        dom0_iomem_permission_t  iomem_permission;
   19.31          uint8_t                  pad[128];
   19.32      } u;
   19.33  } dom0_op_t;
    20.1 --- a/xen/include/xen/compiler.h	Sat Dec 31 13:11:47 2005 +0100
    20.2 +++ b/xen/include/xen/compiler.h	Sat Dec 31 14:15:22 2005 +0100
    20.3 @@ -19,4 +19,10 @@
    20.4  #define __attribute_used__ __attribute__((__unused__))
    20.5  #endif
    20.6  
    20.7 +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
    20.8 +#define __must_check __attribute__((warn_unused_result))
    20.9 +#else
   20.10 +#define __must_check
   20.11 +#endif
   20.12 +
   20.13  #endif /* __LINUX_COMPILER_H */
    21.1 --- a/xen/include/xen/iocap.h	Sat Dec 31 13:11:47 2005 +0100
    21.2 +++ b/xen/include/xen/iocap.h	Sat Dec 31 14:15:22 2005 +0100
    21.3 @@ -10,4 +10,25 @@
    21.4  #include <xen/rangeset.h>
    21.5  #include <asm/iocap.h>
    21.6  
    21.7 +#define iomem_permit_access(d, s, e)                    \
    21.8 +    rangeset_add_range((d)->iomem_caps, s, e)
    21.9 +#define iomem_deny_access(d, s, e)                      \
   21.10 +    rangeset_remove_range((d)->iomem_caps, s, e)
   21.11 +#define iomem_access_permitted(d, s, e)                 \
   21.12 +    rangeset_contains_range((d)->iomem_caps, s, e)
   21.13 +
   21.14 +#define irq_permit_access(d, i)                         \
   21.15 +    rangeset_add_singleton((d)->irq_caps, i)
   21.16 +#define irq_deny_access(d, i)                           \
   21.17 +    rangeset_remove_singleton((d)->irq_caps, i)
   21.18 +#define irqs_permit_access(d, s, e)                     \
   21.19 +    rangeset_add_range((d)->irq_caps, s, e)
   21.20 +#define irqs_deny_access(d, s, e)                       \
   21.21 +    rangeset_remove_range((d)->irq_caps, s, e)
   21.22 +#define irq_access_permitted(d, i)                      \
   21.23 +    rangeset_contains_singleton((d)->irq_caps, i)
   21.24 +
   21.25 +#define multipage_allocation_permitted(d)               \
   21.26 +    (!rangeset_is_empty((d)->iomem_caps))
   21.27 +
   21.28  #endif /* __XEN_IOCAP_H__ */
    22.1 --- a/xen/include/xen/rangeset.h	Sat Dec 31 13:11:47 2005 +0100
    22.2 +++ b/xen/include/xen/rangeset.h	Sat Dec 31 14:15:22 2005 +0100
    22.3 @@ -43,20 +43,23 @@ void rangeset_destroy(
    22.4  #define _RANGESETF_prettyprint_hex 0
    22.5  #define RANGESETF_prettyprint_hex  (1U << _RANGESETF_prettyprint_hex)
    22.6  
    22.7 +int __must_check rangeset_is_empty(
    22.8 +    struct rangeset *r);
    22.9 +
   22.10  /* Add/remove/query a numeric range. */
   22.11 -int rangeset_add_range(
   22.12 +int __must_check rangeset_add_range(
   22.13      struct rangeset *r, unsigned long s, unsigned long e);
   22.14 -int rangeset_remove_range(
   22.15 +int __must_check rangeset_remove_range(
   22.16      struct rangeset *r, unsigned long s, unsigned long e);
   22.17 -int rangeset_contains_range(
   22.18 +int __must_check rangeset_contains_range(
   22.19      struct rangeset *r, unsigned long s, unsigned long e);
   22.20  
   22.21  /* Add/remove/query a single number. */
   22.22 -int rangeset_add_singleton(
   22.23 +int __must_check rangeset_add_singleton(
   22.24      struct rangeset *r, unsigned long s);
   22.25 -int rangeset_remove_singleton(
   22.26 +int __must_check rangeset_remove_singleton(
   22.27      struct rangeset *r, unsigned long s);
   22.28 -int rangeset_contains_singleton(
   22.29 +int __must_check rangeset_contains_singleton(
   22.30      struct rangeset *r, unsigned long s);
   22.31  
   22.32  /* Rangeset pretty printing. */
    23.1 --- a/xen/include/xen/sched.h	Sat Dec 31 13:11:47 2005 +0100
    23.2 +++ b/xen/include/xen/sched.h	Sat Dec 31 14:15:22 2005 +0100
    23.3 @@ -11,6 +11,7 @@
    23.4  #include <xen/time.h>
    23.5  #include <xen/ac_timer.h>
    23.6  #include <xen/grant_table.h>
    23.7 +#include <xen/rangeset.h>
    23.8  #include <asm/domain.h>
    23.9  
   23.10  extern unsigned long volatile jiffies;
   23.11 @@ -128,6 +129,10 @@ struct domain
   23.12      u16              pirq_to_evtchn[NR_PIRQS];
   23.13      u32              pirq_mask[NR_PIRQS/32];
   23.14  
   23.15 +    /* I/O capabilities (access to IRQs and memory-mapped I/O). */
   23.16 +    struct rangeset *iomem_caps;
   23.17 +    struct rangeset *irq_caps;
   23.18 +
   23.19      unsigned long    domain_flags;
   23.20      unsigned long    vm_assist;
   23.21  
   23.22 @@ -381,23 +386,20 @@ extern struct domain *domain_list;
   23.23   /* Is this domain privileged? */
   23.24  #define _DOMF_privileged       1
   23.25  #define DOMF_privileged        (1UL<<_DOMF_privileged)
   23.26 - /* May this domain do IO to physical devices? */
   23.27 -#define _DOMF_physdev_access   2
   23.28 -#define DOMF_physdev_access    (1UL<<_DOMF_physdev_access)
   23.29   /* Guest shut itself down for some reason. */
   23.30 -#define _DOMF_shutdown         3
   23.31 +#define _DOMF_shutdown         2
   23.32  #define DOMF_shutdown          (1UL<<_DOMF_shutdown)
   23.33   /* Guest is in process of shutting itself down (becomes DOMF_shutdown). */
   23.34 -#define _DOMF_shuttingdown     4
   23.35 +#define _DOMF_shuttingdown     3
   23.36  #define DOMF_shuttingdown      (1UL<<_DOMF_shuttingdown)
   23.37   /* Death rattle. */
   23.38 -#define _DOMF_dying            5
   23.39 +#define _DOMF_dying            4
   23.40  #define DOMF_dying             (1UL<<_DOMF_dying)
   23.41   /* Domain is paused by controller software. */
   23.42 -#define _DOMF_ctrl_pause       6
   23.43 +#define _DOMF_ctrl_pause       5
   23.44  #define DOMF_ctrl_pause        (1UL<<_DOMF_ctrl_pause)
   23.45   /* Domain is being debugged by controller software. */
   23.46 -#define _DOMF_debugging        7
   23.47 +#define _DOMF_debugging        6
   23.48  #define DOMF_debugging         (1UL<<_DOMF_debugging)
   23.49  
   23.50  
   23.51 @@ -425,8 +427,6 @@ static inline void vcpu_unblock(struct v
   23.52  
   23.53  #define IS_PRIV(_d)                                         \
   23.54      (test_bit(_DOMF_privileged, &(_d)->domain_flags))
   23.55 -#define IS_CAPABLE_PHYSDEV(_d)                              \
   23.56 -    (test_bit(_DOMF_physdev_access, &(_d)->domain_flags))
   23.57  
   23.58  #define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist))
   23.59