diff options
author | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-12-31 14:15:22 +0100 |
---|---|---|
committer | kaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk> | 2005-12-31 14:15:22 +0100 |
commit | 7e127cd35f6fd48eff4b9f8958eef8fac2b846aa (patch) | |
tree | d987ff8463d4e7d308925d8fa34c478f22865bd0 | |
parent | a8f5fb85087a4ebb9319fe6687eb60f29acbdb35 (diff) | |
download | xen-7e127cd35f6fd48eff4b9f8958eef8fac2b846aa.tar.gz xen-7e127cd35f6fd48eff4b9f8958eef8fac2b846aa.tar.bz2 xen-7e127cd35f6fd48eff4b9f8958eef8fac2b846aa.zip |
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>
-rw-r--r-- | tools/libxc/xc_domain.c | 32 | ||||
-rw-r--r-- | tools/libxc/xenctrl.h | 11 | ||||
-rw-r--r-- | tools/python/xen/lowlevel/xc/xc.c | 65 | ||||
-rw-r--r-- | xen/arch/ia64/xen/domain.c | 5 | ||||
-rw-r--r-- | xen/arch/ia64/xen/irq.c | 3 | ||||
-rw-r--r-- | xen/arch/x86/dom0_ops.c | 14 | ||||
-rw-r--r-- | xen/arch/x86/domain_build.c | 22 | ||||
-rw-r--r-- | xen/arch/x86/irq.c | 4 | ||||
-rw-r--r-- | xen/arch/x86/mm.c | 7 | ||||
-rw-r--r-- | xen/arch/x86/physdev.c | 7 | ||||
-rw-r--r-- | xen/arch/x86/traps.c | 4 | ||||
-rw-r--r-- | xen/common/dom0_ops.c | 49 | ||||
-rw-r--r-- | xen/common/domain.c | 7 | ||||
-rw-r--r-- | xen/common/event_channel.c | 4 | ||||
-rw-r--r-- | xen/common/memory.c | 4 | ||||
-rw-r--r-- | xen/common/rangeset.c | 6 | ||||
-rw-r--r-- | xen/drivers/char/ns16550.c | 3 | ||||
-rw-r--r-- | xen/include/asm-x86/iocap.h | 9 | ||||
-rw-r--r-- | xen/include/public/dom0_ops.h | 17 | ||||
-rw-r--r-- | xen/include/xen/compiler.h | 6 | ||||
-rw-r--r-- | xen/include/xen/iocap.h | 21 | ||||
-rw-r--r-- | xen/include/xen/rangeset.h | 15 | ||||
-rw-r--r-- | xen/include/xen/sched.h | 20 |
23 files changed, 276 insertions, 59 deletions
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index fe3cf55618..b018318d62 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -404,6 +404,38 @@ int xc_domain_setinfo(int xc_handle, } +int xc_domain_irq_permission(int xc_handle, + uint32_t domid, + uint8_t pirq, + uint8_t allow_access) +{ + dom0_op_t op; + + op.cmd = DOM0_IRQ_PERMISSION; + op.u.irq_permission.domain = domid; + op.u.irq_permission.pirq = pirq; + op.u.irq_permission.allow_access = allow_access; + + return do_dom0_op(xc_handle, &op); +} + +int xc_domain_iomem_permission(int xc_handle, + uint32_t domid, + unsigned long first_pfn, + unsigned long nr_pfns, + uint8_t allow_access) +{ + dom0_op_t op; + + op.cmd = DOM0_IOMEM_PERMISSION; + op.u.iomem_permission.domain = domid; + op.u.iomem_permission.first_pfn = first_pfn; + op.u.iomem_permission.nr_pfns = nr_pfns; + op.u.iomem_permission.allow_access = allow_access; + + return do_dom0_op(xc_handle, &op); +} + /* * Local variables: * mode: C diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 6700bd1c0d..f558b5985e 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -380,6 +380,17 @@ int xc_domain_ioport_permission(int xc_handle, uint32_t nr_ports, uint32_t allow_access); +int xc_domain_irq_permission(int xc_handle, + uint32_t domid, + uint8_t pirq, + uint8_t allow_access); + +int xc_domain_iomem_permission(int xc_handle, + uint32_t domid, + unsigned long first_pfn, + unsigned long nr_pfns, + uint8_t allow_access); + unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid, unsigned long mfn); diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 95b0a9f101..30f0ef6d81 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -774,6 +774,52 @@ static PyObject *pyxc_domain_ioport_permission(XcObject *self, return zero; } +static PyObject *pyxc_domain_irq_permission(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + uint32_t dom; + int pirq, allow_access, ret; + + static char *kwd_list[] = { "dom", "pirq", "allow_access", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list, + &dom, &pirq, &allow_access) ) + return NULL; + + ret = xc_domain_irq_permission( + xc->xc_handle, dom, pirq, allow_access); + if ( ret != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + +static PyObject *pyxc_domain_iomem_permission(PyObject *self, + PyObject *args, + PyObject *kwds) +{ + XcObject *xc = (XcObject *)self; + uint32_t dom; + unsigned long first_pfn, nr_pfns, allow_access, ret; + + static char *kwd_list[] = { "dom", "first_pfn", "nr_pfns", "allow_access", NULL }; + + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illi", kwd_list, + &dom, &first_pfn, &nr_pfns, &allow_access) ) + return NULL; + + ret = xc_domain_iomem_permission( + xc->xc_handle, dom, first_pfn, nr_pfns, allow_access); + if ( ret != 0 ) + return PyErr_SetFromErrno(xc_error); + + Py_INCREF(zero); + return zero; +} + static PyObject *dom_op(XcObject *self, PyObject *args, int (*fn)(int, uint32_t)) @@ -1070,6 +1116,25 @@ static PyMethodDef pyxc_methods[] = { " allow_access [int]: Non-zero means enable access; else disable access\n\n" "Returns: [int] 0 on success; -1 on error.\n" }, + { "domain_irq_permission", + (PyCFunction)pyxc_domain_irq_permission, + METH_VARARGS | METH_KEYWORDS, "\n" + "Allow a domain access to a physical IRQ\n" + " dom [int]: Identifier of domain to be allowed access.\n" + " pirq [int]: The Physical IRQ\n" + " allow_access [int]: Non-zero means enable access; else disable access\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + + { "domain_iomem_permission", + (PyCFunction)pyxc_domain_iomem_permission, + METH_VARARGS | METH_KEYWORDS, "\n" + "Allow a domain access to a range of IO memory pages\n" + " dom [int]: Identifier of domain to be allowed access.\n" + " first_pfn [long]: First page of I/O Memory\n" + " nr_pfns [long]: Number of pages of I/O Memory (>0)\n" + " allow_access [int]: Non-zero means enable access; else disable access\n\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + { "pages_to_kib", (PyCFunction)pyxc_pages_to_kib, METH_VARARGS, "\n" diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 5b68519bbe..b784372cd8 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -765,7 +765,10 @@ void alloc_dom0(void) */ void physdev_init_dom0(struct domain *d) { - set_bit(_DOMF_physdev_access, &d->domain_flags); + if (iomem_permit_access(d, 0UL, ~0UL)) + BUG(); + if (irqs_permit_access(d, 0, NR_PIRQS-1)) + BUG(); } unsigned int vmx_dom0 = 0; diff --git a/xen/arch/ia64/xen/irq.c b/xen/arch/ia64/xen/irq.c index b694d62bc9..1537873e04 100644 --- a/xen/arch/ia64/xen/irq.c +++ b/xen/arch/ia64/xen/irq.c @@ -1378,9 +1378,6 @@ int pirq_guest_bind(struct vcpu *d, int irq, int will_share) unsigned long flags; int rc = 0; - if ( !IS_CAPABLE_PHYSDEV(d->domain) ) - return -EPERM; - spin_lock_irqsave(&desc->lock, flags); action = (irq_guest_action_t *)desc->action; diff --git a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c index 022fa33e35..5a4f493ce0 100644 --- a/xen/arch/x86/dom0_ops.c +++ b/xen/arch/x86/dom0_ops.c @@ -152,14 +152,12 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op) op->u.ioport_permission.domain)) == NULL) ) break; - ret = 0; - if ( np > 0 ) - { - if ( op->u.ioport_permission.allow_access ) - ioport_range_permit(d, fp, fp + np - 1); - else - ioport_range_deny(d, fp, fp + np - 1); - } + if ( np == 0 ) + ret = 0; + else if ( op->u.ioport_permission.allow_access ) + ret = ioports_permit_access(d, fp, fp + np - 1); + else + ret = ioports_deny_access(d, fp, fp + np - 1); put_domain(d); } diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index cdeb08265c..d08f2c12fb 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -94,7 +94,7 @@ static struct pfn_info *alloc_chunk(struct domain *d, unsigned long max_pages) return page; } -static void process_dom0_ioports_disable() +static void process_dom0_ioports_disable(void) { unsigned long io_from, io_to; char *t, *u, *s = opt_dom0_ioports_disable; @@ -126,7 +126,8 @@ static void process_dom0_ioports_disable() printk("Disabling dom0 access to ioport range %04lx-%04lx\n", io_from, io_to); - ioport_range_deny(dom0, io_from, io_to); + if ( ioports_deny_access(dom0, io_from, io_to) != 0 ) + BUG(); } } @@ -741,24 +742,29 @@ int construct_dom0(struct domain *d, printk("dom0: shadow setup done\n"); } + i = 0; + /* DOM0 is permitted full I/O capabilities. */ - ioport_range_permit(dom0, 0, 0xFFFF); - set_bit(_DOMF_physdev_access, &dom0->domain_flags); + i |= ioports_permit_access(dom0, 0, 0xFFFF); + i |= iomem_permit_access(dom0, 0UL, ~0UL); + i |= irqs_permit_access(dom0, 0, NR_PIRQS-1); /* * Modify I/O port access permissions. */ /* Master Interrupt Controller (PIC). */ - ioport_range_deny(dom0, 0x20, 0x21); + i |= ioports_deny_access(dom0, 0x20, 0x21); /* Slave Interrupt Controller (PIC). */ - ioport_range_deny(dom0, 0xA0, 0xA1); + i |= ioports_deny_access(dom0, 0xA0, 0xA1); /* Interval Timer (PIT). */ - ioport_range_deny(dom0, 0x40, 0x43); + i |= ioports_deny_access(dom0, 0x40, 0x43); /* PIT Channel 2 / PC Speaker Control. */ - ioport_range_deny(dom0, 0x61, 0x61); + i |= ioports_deny_access(dom0, 0x61, 0x61); /* Command-line I/O ranges. */ process_dom0_ioports_disable(); + BUG_ON(i != 0); + return 0; } diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index e0553486bc..a1aee360c3 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -199,16 +199,12 @@ int pirq_guest_unmask(struct domain *d) int pirq_guest_bind(struct vcpu *v, int irq, int will_share) { unsigned int vector = irq_to_vector(irq); - struct domain *d = v->domain; irq_desc_t *desc = &irq_desc[vector]; irq_guest_action_t *action; unsigned long flags; int rc = 0; cpumask_t cpumask = CPU_MASK_NONE; - if ( !IS_CAPABLE_PHYSDEV(d) ) - return -EPERM; - if ( vector == 0 ) return -EBUSY; diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index e6a99065e3..683c4b7534 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -96,6 +96,7 @@ #include <xen/softirq.h> #include <xen/domain_page.h> #include <xen/event.h> +#include <xen/iocap.h> #include <asm/shadow.h> #include <asm/page.h> #include <asm/flushtlb.h> @@ -437,7 +438,6 @@ get_page_from_l1e( unsigned long mfn = l1e_get_pfn(l1e); struct pfn_info *page = pfn_to_page(mfn); int okay; - extern int domain_iomem_in_pfn(struct domain *d, unsigned long pfn); if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) ) return 1; @@ -455,8 +455,7 @@ get_page_from_l1e( if ( d == dom_io ) d = current->domain; - if ( (!IS_PRIV(d)) && - (!IS_CAPABLE_PHYSDEV(d) || !domain_iomem_in_pfn(d, mfn)) ) + if ( !iomem_access_permitted(d, mfn, mfn) ) { MEM_LOG("Non-privileged attempt to map I/O space %08lx", mfn); return 0; @@ -1887,7 +1886,7 @@ int do_mmuext_op( break; case MMUEXT_FLUSH_CACHE: - if ( unlikely(!IS_CAPABLE_PHYSDEV(d)) ) + if ( unlikely(!cache_flush_permitted(d)) ) { MEM_LOG("Non-physdev domain tried to FLUSH_CACHE."); okay = 0; diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index 0e7c1c10c5..e8cb5b8707 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -14,13 +14,6 @@ extern int ioapic_guest_read(int apicid, int address, u32 *pval); extern int ioapic_guest_write(int apicid, int address, u32 pval); -/* Check if a domain controls a device with IO memory within frame @pfn. - * Returns: 1 if the domain should be allowed to map @pfn, 0 otherwise. */ -int domain_iomem_in_pfn(struct domain *p, unsigned long pfn) -{ - return 0; -} - /* * Demuxing hypercall. */ diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index 8216452fd0..a4be3db3b3 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -623,7 +623,7 @@ static inline int admin_io_okay( unsigned int port, unsigned int bytes, struct vcpu *v, struct cpu_user_regs *regs) { - return ioport_range_access_permitted(v->domain, port, port + bytes - 1); + return ioports_access_permitted(v->domain, port, port + bytes - 1); } /* Check admin limits. Silently fail the access if it is disallowed. */ @@ -863,7 +863,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs) case 0x09: /* WBINVD */ /* Ignore the instruction if unprivileged. */ - if ( !IS_CAPABLE_PHYSDEV(v->domain) ) + if ( !cache_flush_permitted(v->domain) ) DPRINTK("Non-physdev domain attempted WBINVD.\n"); else wbinvd(); diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index a4cbc48b4f..97cd571376 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -16,6 +16,7 @@ #include <xen/domain_page.h> #include <xen/trace.h> #include <xen/console.h> +#include <xen/iocap.h> #include <asm/current.h> #include <public/dom0_ops.h> #include <public/sched_ctl.h> @@ -582,6 +583,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) } } break; + case DOM0_SETDEBUGGING: { struct domain *d; @@ -599,6 +601,53 @@ long do_dom0_op(dom0_op_t *u_dom0_op) } break; + case DOM0_IRQ_PERMISSION: + { + struct domain *d; + unsigned int pirq = op->u.irq_permission.pirq; + + ret = -EINVAL; + if ( pirq >= NR_PIRQS ) + break; + + ret = -ESRCH; + d = find_domain_by_id(op->u.irq_permission.domain); + if ( d == NULL ) + break; + + if ( op->u.irq_permission.allow_access ) + ret = irq_permit_access(d, pirq); + else + ret = irq_deny_access(d, pirq); + + put_domain(d); + } + break; + + case DOM0_IOMEM_PERMISSION: + { + struct domain *d; + unsigned long pfn = op->u.iomem_permission.first_pfn; + unsigned long nr_pfns = op->u.iomem_permission.nr_pfns; + + ret = -EINVAL; + if ( (pfn + nr_pfns - 1) < pfn ) /* wrap? */ + break; + + ret = -ESRCH; + d = find_domain_by_id(op->u.iomem_permission.domain); + if ( d == NULL ) + break; + + if ( op->u.iomem_permission.allow_access ) + ret = iomem_permit_access(d, pfn, pfn + nr_pfns - 1); + else + ret = iomem_deny_access(d, pfn, pfn + nr_pfns - 1); + + put_domain(d); + } + break; + #ifdef PERF_COUNTERS case DOM0_PERFCCONTROL: { diff --git a/xen/common/domain.c b/xen/common/domain.c index 46f45950b2..0f206d8e1c 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -60,7 +60,12 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) rangeset_domain_initialise(d); - if ( arch_do_createdomain(v) != 0 ) + d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex); + d->irq_caps = rangeset_new(d, "Interrupts", 0); + + if ( (d->iomem_caps == NULL) || + (d->irq_caps == NULL) || + (arch_do_createdomain(v) != 0) ) goto fail3; if ( !is_idle_task(d) ) diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index eeccc0e160..fdda1e86b8 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -22,6 +22,7 @@ #include <xen/sched.h> #include <xen/event.h> #include <xen/irq.h> +#include <xen/iocap.h> #include <asm/current.h> #include <public/xen.h> @@ -242,6 +243,9 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind) if ( pirq >= ARRAY_SIZE(d->pirq_to_evtchn) ) return -EINVAL; + if ( !irq_access_permitted(d, pirq) ) + return -EPERM; + spin_lock(&d->evtchn_lock); if ( d->pirq_to_evtchn[pirq] != 0 ) diff --git a/xen/common/memory.c b/xen/common/memory.c index 45934fdf76..847fcbb0cc 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -15,6 +15,7 @@ #include <xen/sched.h> #include <xen/event.h> #include <xen/shadow.h> +#include <xen/iocap.h> #include <asm/current.h> #include <asm/hardirq.h> #include <public/memory.h> @@ -35,7 +36,8 @@ increase_reservation( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) ) return 0; - if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) ) + if ( (extent_order != 0) && + !multipage_allocation_permitted(current->domain) ) { DPRINTK("Only I/O-capable domains may allocate multi-page extents.\n"); return 0; diff --git a/xen/common/rangeset.c b/xen/common/rangeset.c index a1680a29f2..de17a90ec5 100644 --- a/xen/common/rangeset.c +++ b/xen/common/rangeset.c @@ -253,6 +253,12 @@ int rangeset_contains_singleton( return rangeset_contains_range(r, s, s); } +int rangeset_is_empty( + struct rangeset *r) +{ + return list_empty(&r->range_list); +} + struct rangeset *rangeset_new( struct domain *d, char *name, unsigned int flags) { diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c index 6784983b3b..8ef838d3db 100644 --- a/xen/drivers/char/ns16550.c +++ b/xen/drivers/char/ns16550.c @@ -237,7 +237,8 @@ static void ns16550_init_postirq(struct serial_port *port) static void ns16550_endboot(struct serial_port *port) { struct ns16550 *uart = port->uart; - ioport_range_deny(dom0, uart->io_base, uart->io_base + 7); + if ( ioports_deny_access(dom0, uart->io_base, uart->io_base + 7) != 0 ) + BUG(); } #else #define ns16550_endboot NULL diff --git a/xen/include/asm-x86/iocap.h b/xen/include/asm-x86/iocap.h index e60b82ff3a..c7463cb6f2 100644 --- a/xen/include/asm-x86/iocap.h +++ b/xen/include/asm-x86/iocap.h @@ -7,11 +7,14 @@ #ifndef __X86_IOCAP_H__ #define __X86_IOCAP_H__ -#define ioport_range_permit(d, s, e) \ +#define ioports_permit_access(d, s, e) \ rangeset_add_range((d)->arch.ioport_caps, s, e) -#define ioport_range_deny(d, s, e) \ +#define ioports_deny_access(d, s, e) \ rangeset_remove_range((d)->arch.ioport_caps, s, e) -#define ioport_range_access_permitted(d, s, e) \ +#define ioports_access_permitted(d, s, e) \ rangeset_contains_range((d)->arch.ioport_caps, s, e) +#define cache_flush_permitted(d) \ + (!rangeset_is_empty((d)->iomem_caps)) + #endif /* __X86_IOCAP_H__ */ diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index b6b5914200..a2c66be1f4 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -410,6 +410,21 @@ typedef struct { uint8_t enable; } dom0_setdebugging_t; +#define DOM0_IRQ_PERMISSION 46 +typedef struct { + domid_t domain; /* domain to be affected */ + uint8_t pirq; + uint8_t allow_access; /* flag to specify enable/disable of IRQ access */ +} dom0_irq_permission_t; + +#define DOM0_IOMEM_PERMISSION 47 +typedef struct { + domid_t domain; /* domain to be affected */ + unsigned long first_pfn; /* first page (physical page number) in range */ + unsigned long nr_pfns; /* number of pages in range (>0) */ + uint8_t allow_access; /* allow (!0) or deny (0) access to range? */ +} dom0_iomem_permission_t; + typedef struct { uint32_t cmd; uint32_t interface_version; /* DOM0_INTERFACE_VERSION */ @@ -448,6 +463,8 @@ typedef struct { dom0_max_vcpus_t max_vcpus; dom0_setdomainhandle_t setdomainhandle; dom0_setdebugging_t setdebugging; + dom0_irq_permission_t irq_permission; + dom0_iomem_permission_t iomem_permission; uint8_t pad[128]; } u; } dom0_op_t; diff --git a/xen/include/xen/compiler.h b/xen/include/xen/compiler.h index f0c5fbf17a..29acdc59e8 100644 --- a/xen/include/xen/compiler.h +++ b/xen/include/xen/compiler.h @@ -19,4 +19,10 @@ #define __attribute_used__ __attribute__((__unused__)) #endif +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define __must_check __attribute__((warn_unused_result)) +#else +#define __must_check +#endif + #endif /* __LINUX_COMPILER_H */ diff --git a/xen/include/xen/iocap.h b/xen/include/xen/iocap.h index 967f70fe4b..db461b9dcb 100644 --- a/xen/include/xen/iocap.h +++ b/xen/include/xen/iocap.h @@ -10,4 +10,25 @@ #include <xen/rangeset.h> #include <asm/iocap.h> +#define iomem_permit_access(d, s, e) \ + rangeset_add_range((d)->iomem_caps, s, e) +#define iomem_deny_access(d, s, e) \ + rangeset_remove_range((d)->iomem_caps, s, e) +#define iomem_access_permitted(d, s, e) \ + rangeset_contains_range((d)->iomem_caps, s, e) + +#define irq_permit_access(d, i) \ + rangeset_add_singleton((d)->irq_caps, i) +#define irq_deny_access(d, i) \ + rangeset_remove_singleton((d)->irq_caps, i) +#define irqs_permit_access(d, s, e) \ + rangeset_add_range((d)->irq_caps, s, e) +#define irqs_deny_access(d, s, e) \ + rangeset_remove_range((d)->irq_caps, s, e) +#define irq_access_permitted(d, i) \ + rangeset_contains_singleton((d)->irq_caps, i) + +#define multipage_allocation_permitted(d) \ + (!rangeset_is_empty((d)->iomem_caps)) + #endif /* __XEN_IOCAP_H__ */ diff --git a/xen/include/xen/rangeset.h b/xen/include/xen/rangeset.h index ffd14ad17d..d4a8e00393 100644 --- a/xen/include/xen/rangeset.h +++ b/xen/include/xen/rangeset.h @@ -43,20 +43,23 @@ void rangeset_destroy( #define _RANGESETF_prettyprint_hex 0 #define RANGESETF_prettyprint_hex (1U << _RANGESETF_prettyprint_hex) +int __must_check rangeset_is_empty( + struct rangeset *r); + /* Add/remove/query a numeric range. */ -int rangeset_add_range( +int __must_check rangeset_add_range( struct rangeset *r, unsigned long s, unsigned long e); -int rangeset_remove_range( +int __must_check rangeset_remove_range( struct rangeset *r, unsigned long s, unsigned long e); -int rangeset_contains_range( +int __must_check rangeset_contains_range( struct rangeset *r, unsigned long s, unsigned long e); /* Add/remove/query a single number. */ -int rangeset_add_singleton( +int __must_check rangeset_add_singleton( struct rangeset *r, unsigned long s); -int rangeset_remove_singleton( +int __must_check rangeset_remove_singleton( struct rangeset *r, unsigned long s); -int rangeset_contains_singleton( +int __must_check rangeset_contains_singleton( struct rangeset *r, unsigned long s); /* Rangeset pretty printing. */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 4bc824741a..c686394b7f 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -11,6 +11,7 @@ #include <xen/time.h> #include <xen/ac_timer.h> #include <xen/grant_table.h> +#include <xen/rangeset.h> #include <asm/domain.h> extern unsigned long volatile jiffies; @@ -128,6 +129,10 @@ struct domain u16 pirq_to_evtchn[NR_PIRQS]; u32 pirq_mask[NR_PIRQS/32]; + /* I/O capabilities (access to IRQs and memory-mapped I/O). */ + struct rangeset *iomem_caps; + struct rangeset *irq_caps; + unsigned long domain_flags; unsigned long vm_assist; @@ -381,23 +386,20 @@ extern struct domain *domain_list; /* Is this domain privileged? */ #define _DOMF_privileged 1 #define DOMF_privileged (1UL<<_DOMF_privileged) - /* May this domain do IO to physical devices? */ -#define _DOMF_physdev_access 2 -#define DOMF_physdev_access (1UL<<_DOMF_physdev_access) /* Guest shut itself down for some reason. */ -#define _DOMF_shutdown 3 +#define _DOMF_shutdown 2 #define DOMF_shutdown (1UL<<_DOMF_shutdown) /* Guest is in process of shutting itself down (becomes DOMF_shutdown). */ -#define _DOMF_shuttingdown 4 +#define _DOMF_shuttingdown 3 #define DOMF_shuttingdown (1UL<<_DOMF_shuttingdown) /* Death rattle. */ -#define _DOMF_dying 5 +#define _DOMF_dying 4 #define DOMF_dying (1UL<<_DOMF_dying) /* Domain is paused by controller software. */ -#define _DOMF_ctrl_pause 6 +#define _DOMF_ctrl_pause 5 #define DOMF_ctrl_pause (1UL<<_DOMF_ctrl_pause) /* Domain is being debugged by controller software. */ -#define _DOMF_debugging 7 +#define _DOMF_debugging 6 #define DOMF_debugging (1UL<<_DOMF_debugging) @@ -425,8 +427,6 @@ static inline void vcpu_unblock(struct vcpu *v) #define IS_PRIV(_d) \ (test_bit(_DOMF_privileged, &(_d)->domain_flags)) -#define IS_CAPABLE_PHYSDEV(_d) \ - (test_bit(_DOMF_physdev_access, &(_d)->domain_flags)) #define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist)) |