aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/ia64/xen/domain.c6
-rw-r--r--xen/arch/x86/dom0_ops.c20
-rw-r--r--xen/arch/x86/domain.c29
-rw-r--r--xen/arch/x86/domain_build.c25
-rw-r--r--xen/arch/x86/physdev.c26
-rw-r--r--xen/arch/x86/setup.c5
-rw-r--r--xen/arch/x86/traps.c13
-rw-r--r--xen/common/domain.c27
-rw-r--r--xen/common/rangeset.c2
-rw-r--r--xen/drivers/char/ns16550.c4
-rw-r--r--xen/include/asm-ia64/domain.h2
-rw-r--r--xen/include/asm-ia64/iocap.h10
-rw-r--r--xen/include/asm-x86/domain.h4
-rw-r--r--xen/include/asm-x86/iocap.h17
-rw-r--r--xen/include/asm-x86/physdev.h17
-rw-r--r--xen/include/xen/domain.h4
-rw-r--r--xen/include/xen/iocap.h13
17 files changed, 107 insertions, 117 deletions
diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c
index a1fc49d7bd..5b68519bbe 100644
--- a/xen/arch/ia64/xen/domain.c
+++ b/xen/arch/ia64/xen/domain.c
@@ -181,7 +181,7 @@ static void init_switch_stack(struct vcpu *v)
memset(v->arch._thread.fph,0,sizeof(struct ia64_fpreg)*96);
}
-void arch_do_createdomain(struct vcpu *v)
+int arch_do_createdomain(struct vcpu *v)
{
struct domain *d = v->domain;
struct thread_info *ti = alloc_thread_info(v);
@@ -248,7 +248,9 @@ void arch_do_createdomain(struct vcpu *v)
}
} else
d->arch.mm = NULL;
- printf ("arch_do_create_domain: domain=%p\n", d);
+ printf ("arch_do_create_domain: domain=%p\n", d);
+
+ return 0;
}
void arch_getdomaininfo_ctxt(struct vcpu *v, struct vcpu_guest_context *c)
diff --git a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c
index 1e4b0978c3..022fa33e35 100644
--- a/xen/arch/x86/dom0_ops.c
+++ b/xen/arch/x86/dom0_ops.c
@@ -17,6 +17,7 @@
#include <asm/msr.h>
#include <xen/trace.h>
#include <xen/console.h>
+#include <xen/iocap.h>
#include <asm/shadow.h>
#include <asm/irq.h>
#include <asm/processor.h>
@@ -141,7 +142,6 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
struct domain *d;
unsigned int fp = op->u.ioport_permission.first_port;
unsigned int np = op->u.ioport_permission.nr_ports;
- unsigned int p;
ret = -EINVAL;
if ( (fp + np) > 65536 )
@@ -152,25 +152,13 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
op->u.ioport_permission.domain)) == NULL) )
break;
- ret = -ENOMEM;
- if ( d->arch.iobmp_mask == NULL )
- {
- if ( (d->arch.iobmp_mask = xmalloc_array(
- u8, IOBMP_BYTES)) == NULL )
- {
- put_domain(d);
- break;
- }
- memset(d->arch.iobmp_mask, 0xFF, IOBMP_BYTES);
- }
-
ret = 0;
- for ( p = fp; p < (fp + np); p++ )
+ if ( np > 0 )
{
if ( op->u.ioport_permission.allow_access )
- clear_bit(p, d->arch.iobmp_mask);
+ ioport_range_permit(d, fp, fp + np - 1);
else
- set_bit(p, d->arch.iobmp_mask);
+ ioport_range_deny(d, fp, fp + np - 1);
}
put_domain(d);
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index 2c89207e1b..49603696c5 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -20,6 +20,7 @@
#include <xen/delay.h>
#include <xen/softirq.h>
#include <xen/grant_table.h>
+#include <xen/iocap.h>
#include <asm/regs.h>
#include <asm/mc146818rtc.h>
#include <asm/system.h>
@@ -36,7 +37,6 @@
#include <xen/elf.h>
#include <asm/vmx.h>
#include <asm/msr.h>
-#include <asm/physdev.h>
#include <xen/kernel.h>
#include <xen/multicall.h>
@@ -249,21 +249,34 @@ void free_perdomain_pt(struct domain *d)
#endif
}
-void arch_do_createdomain(struct vcpu *v)
+int arch_do_createdomain(struct vcpu *v)
{
struct domain *d = v->domain;
l1_pgentry_t gdt_l1e;
- int vcpuid, pdpt_order;
+ int vcpuid, pdpt_order, rc;
#ifdef __x86_64__
int i;
#endif
if ( is_idle_task(d) )
- return;
+ return 0;
+
+ d->arch.ioport_caps =
+ rangeset_new(d, "I/O Ports", RANGESETF_prettyprint_hex);
+ if ( d->arch.ioport_caps == NULL )
+ return -ENOMEM;
+
+ if ( (d->shared_info = alloc_xenheap_page()) == NULL )
+ return -ENOMEM;
+
+ if ( (rc = ptwr_init(d)) != 0 )
+ {
+ free_xenheap_page(d->shared_info);
+ return rc;
+ }
v->arch.schedule_tail = continue_nonidle_task;
- d->shared_info = alloc_xenheap_page();
memset(d->shared_info, 0, PAGE_SIZE);
v->vcpu_info = &d->shared_info->vcpu_info[v->vcpu_id];
v->cpumap = CPUMAP_RUNANYWHERE;
@@ -307,10 +320,10 @@ void arch_do_createdomain(struct vcpu *v)
__PAGE_HYPERVISOR);
#endif
- (void)ptwr_init(d);
-
shadow_lock_init(d);
INIT_LIST_HEAD(&d->arch.free_shadow_frames);
+
+ return 0;
}
void vcpu_migrate_cpu(struct vcpu *v, int newcpu)
@@ -954,8 +967,6 @@ void domain_relinquish_resources(struct domain *d)
BUG_ON(!cpus_empty(d->cpumask));
- physdev_destroy_state(d);
-
ptwr_destroy(d);
/* Drop the in-use references to page-table bases. */
diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
index f3cbf8237f..cdeb08265c 100644
--- a/xen/arch/x86/domain_build.c
+++ b/xen/arch/x86/domain_build.c
@@ -16,13 +16,13 @@
#include <xen/kernel.h>
#include <xen/domain.h>
#include <xen/compile.h>
+#include <xen/iocap.h>
#include <asm/regs.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/desc.h>
#include <asm/i387.h>
-#include <asm/physdev.h>
#include <asm/shadow.h>
static long dom0_nrpages;
@@ -96,7 +96,7 @@ static struct pfn_info *alloc_chunk(struct domain *d, unsigned long max_pages)
static void process_dom0_ioports_disable()
{
- unsigned long io_from, io_to, io_nr;
+ unsigned long io_from, io_to;
char *t, *u, *s = opt_dom0_ioports_disable;
if ( *s == '\0' )
@@ -126,8 +126,7 @@ static void process_dom0_ioports_disable()
printk("Disabling dom0 access to ioport range %04lx-%04lx\n",
io_from, io_to);
- io_nr = io_to - io_from + 1;
- physdev_modify_ioport_access_range(dom0, 0, io_from, io_nr);
+ ioport_range_deny(dom0, io_from, io_to);
}
}
@@ -183,7 +182,6 @@ int construct_dom0(struct domain *d,
/* Machine address of next candidate page-table page. */
unsigned long mpt_alloc;
- extern void physdev_init_dom0(struct domain *);
extern void translate_l2pgtable(
struct domain *d, l1_pgentry_t *p2m, unsigned long l2mfn);
@@ -692,9 +690,6 @@ int construct_dom0(struct domain *d,
zap_low_mappings(l2start);
zap_low_mappings(idle_pg_table_l2);
#endif
-
- /* DOM0 gets access to everything. */
- physdev_init_dom0(d);
init_domain_time(d);
@@ -746,18 +741,22 @@ int construct_dom0(struct domain *d,
printk("dom0: shadow setup done\n");
}
+ /* DOM0 is permitted full I/O capabilities. */
+ ioport_range_permit(dom0, 0, 0xFFFF);
+ set_bit(_DOMF_physdev_access, &dom0->domain_flags);
+
/*
* Modify I/O port access permissions.
*/
/* Master Interrupt Controller (PIC). */
- physdev_modify_ioport_access_range(dom0, 0, 0x20, 2);
+ ioport_range_deny(dom0, 0x20, 0x21);
/* Slave Interrupt Controller (PIC). */
- physdev_modify_ioport_access_range(dom0, 0, 0xA0, 2);
+ ioport_range_deny(dom0, 0xA0, 0xA1);
/* Interval Timer (PIT). */
- physdev_modify_ioport_access_range(dom0, 0, 0x40, 4);
+ ioport_range_deny(dom0, 0x40, 0x43);
/* PIT Channel 2 / PC Speaker Control. */
- physdev_modify_ioport_access_range(dom0, 0, 0x61, 1);
- /* Command-line passed i/o ranges */
+ ioport_range_deny(dom0, 0x61, 0x61);
+ /* Command-line I/O ranges. */
process_dom0_ioports_disable();
return 0;
diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c
index 376419b239..0e7c1c10c5 100644
--- a/xen/arch/x86/physdev.c
+++ b/xen/arch/x86/physdev.c
@@ -14,20 +14,6 @@
extern int ioapic_guest_read(int apicid, int address, u32 *pval);
extern int ioapic_guest_write(int apicid, int address, u32 pval);
-void physdev_modify_ioport_access_range(
- struct domain *d, int enable, int port, int num)
-{
- int i;
- for ( i = port; i < (port + num); i++ )
- (enable ? clear_bit : set_bit)(i, d->arch.iobmp_mask);
-}
-
-void physdev_destroy_state(struct domain *d)
-{
- xfree(d->arch.iobmp_mask);
- d->arch.iobmp_mask = NULL;
-}
-
/* 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)
@@ -120,18 +106,6 @@ long do_physdev_op(physdev_op_t *uop)
return ret;
}
-/* Domain 0 has read access to all devices. */
-void physdev_init_dom0(struct domain *d)
-{
- /* Access to all I/O ports. */
- d->arch.iobmp_mask = xmalloc_array(u8, IOBMP_BYTES);
- BUG_ON(d->arch.iobmp_mask == NULL);
- memset(d->arch.iobmp_mask, 0, IOBMP_BYTES);
-
- set_bit(_DOMF_physdev_access, &d->domain_flags);
-}
-
-
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 38fb25d16e..f27806f8f6 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -388,8 +388,9 @@ void __init __start_xen(multiboot_info_t *mbi)
sort_exception_tables();
- arch_do_createdomain(current);
-
+ if ( arch_do_createdomain(current) != 0 )
+ BUG();
+
/*
* Map default GDT into its final positions in the idle page table. As
* noted in arch_do_createdomain(), we must map for every possible VCPU#.
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 64a6e2a5d7..8216452fd0 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -41,6 +41,7 @@
#include <xen/softirq.h>
#include <xen/domain_page.h>
#include <xen/symbols.h>
+#include <xen/iocap.h>
#include <asm/shadow.h>
#include <asm/system.h>
#include <asm/io.h>
@@ -622,17 +623,7 @@ static inline int admin_io_okay(
unsigned int port, unsigned int bytes,
struct vcpu *v, struct cpu_user_regs *regs)
{
- struct domain *d = v->domain;
- u16 x;
-
- if ( d->arch.iobmp_mask != NULL )
- {
- x = *(u16 *)(d->arch.iobmp_mask + (port >> 3));
- if ( (x & (((1<<bytes)-1) << (port&7))) == 0 )
- return 1;
- }
-
- return 0;
+ return ioport_range_access_permitted(v->domain, port, port + bytes - 1);
}
/* Check admin limits. Silently fail the access if it is disallowed. */
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 3e0f90eded..46f45950b2 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -53,24 +53,16 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
if ( !is_idle_task(d) &&
((evtchn_init(d) != 0) || (grant_table_create(d) != 0)) )
- {
- evtchn_destroy(d);
- free_domain(d);
- return NULL;
- }
+ goto fail1;
if ( (v = alloc_vcpu(d, 0, cpu)) == NULL )
- {
- grant_table_destroy(d);
- evtchn_destroy(d);
- free_domain(d);
- return NULL;
- }
+ goto fail2;
rangeset_domain_initialise(d);
- arch_do_createdomain(v);
-
+ if ( arch_do_createdomain(v) != 0 )
+ goto fail3;
+
if ( !is_idle_task(d) )
{
write_lock(&domlist_lock);
@@ -86,6 +78,15 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
}
return d;
+
+ fail3:
+ rangeset_domain_destroy(d);
+ fail2:
+ grant_table_destroy(d);
+ fail1:
+ evtchn_destroy(d);
+ free_domain(d);
+ return NULL;
}
diff --git a/xen/common/rangeset.c b/xen/common/rangeset.c
index 228986c33a..a1680a29f2 100644
--- a/xen/common/rangeset.c
+++ b/xen/common/rangeset.c
@@ -350,7 +350,7 @@ void rangeset_printk(
spin_lock(&r->lock);
- printk("%10s {", r->name);
+ printk("%-10s {", r->name);
for ( x = first_range(r); x != NULL; x = next_range(r, x) )
{
diff --git a/xen/drivers/char/ns16550.c b/xen/drivers/char/ns16550.c
index b7d24107b6..6784983b3b 100644
--- a/xen/drivers/char/ns16550.c
+++ b/xen/drivers/char/ns16550.c
@@ -13,6 +13,7 @@
#include <xen/irq.h>
#include <xen/sched.h>
#include <xen/serial.h>
+#include <xen/iocap.h>
#include <asm/io.h>
/*
@@ -233,11 +234,10 @@ static void ns16550_init_postirq(struct serial_port *port)
}
#ifdef CONFIG_X86
-#include <asm/physdev.h>
static void ns16550_endboot(struct serial_port *port)
{
struct ns16550 *uart = port->uart;
- physdev_modify_ioport_access_range(dom0, 0, uart->io_base, 8);
+ ioport_range_deny(dom0, uart->io_base, uart->io_base + 7);
}
#else
#define ns16550_endboot NULL
diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h
index 524bd1c348..863def1ff5 100644
--- a/xen/include/asm-ia64/domain.h
+++ b/xen/include/asm-ia64/domain.h
@@ -10,7 +10,7 @@
#include <asm/vmx_platform.h>
#include <xen/list.h>
-extern void arch_do_createdomain(struct vcpu *);
+extern int arch_do_createdomain(struct vcpu *);
extern void domain_relinquish_resources(struct domain *);
diff --git a/xen/include/asm-ia64/iocap.h b/xen/include/asm-ia64/iocap.h
new file mode 100644
index 0000000000..3d8b845d85
--- /dev/null
+++ b/xen/include/asm-ia64/iocap.h
@@ -0,0 +1,10 @@
+/******************************************************************************
+ * iocap.h
+ *
+ * Architecture-specific per-domain I/O capabilities.
+ */
+
+#ifndef __IA64_IOCAP_H__
+#define __IA64_IOCAP_H__
+
+#endif /* __IA64_IOCAP_H__ */
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index 94111fe1d1..513b7d8aff 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -24,8 +24,8 @@ struct arch_domain
/* Writable pagetables. */
struct ptwr_info ptwr[2];
- /* I/O-port access bitmap mask. */
- u8 *iobmp_mask; /* Address of IO bitmap mask, or NULL. */
+ /* I/O-port admin-specified access capabilities. */
+ struct rangeset *ioport_caps;
/* Shadow mode status and controls. */
struct shadow_ops *ops;
diff --git a/xen/include/asm-x86/iocap.h b/xen/include/asm-x86/iocap.h
new file mode 100644
index 0000000000..e60b82ff3a
--- /dev/null
+++ b/xen/include/asm-x86/iocap.h
@@ -0,0 +1,17 @@
+/******************************************************************************
+ * iocap.h
+ *
+ * Architecture-specific per-domain I/O capabilities.
+ */
+
+#ifndef __X86_IOCAP_H__
+#define __X86_IOCAP_H__
+
+#define ioport_range_permit(d, s, e) \
+ rangeset_add_range((d)->arch.ioport_caps, s, e)
+#define ioport_range_deny(d, s, e) \
+ rangeset_remove_range((d)->arch.ioport_caps, s, e)
+#define ioport_range_access_permitted(d, s, e) \
+ rangeset_contains_range((d)->arch.ioport_caps, s, e)
+
+#endif /* __X86_IOCAP_H__ */
diff --git a/xen/include/asm-x86/physdev.h b/xen/include/asm-x86/physdev.h
deleted file mode 100644
index 0b004d4958..0000000000
--- a/xen/include/asm-x86/physdev.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/******************************************************************************
- * physdev.h
- */
-
-#ifndef __XEN_PHYSDEV_H__
-#define __XEN_PHYSDEV_H__
-
-#include <public/physdev.h>
-
-void physdev_modify_ioport_access_range(
- struct domain *d, int enable, int port, int num );
-void physdev_destroy_state(struct domain *d);
-int domain_iomem_in_pfn(struct domain *p, unsigned long pfn);
-long do_physdev_op(physdev_op_t *uop);
-void physdev_init_dom0(struct domain *d);
-
-#endif /* __XEN_PHYSDEV_H__ */
diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h
index 3baf56babd..761bf87a54 100644
--- a/xen/include/xen/domain.h
+++ b/xen/include/xen/domain.h
@@ -13,9 +13,9 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id);
extern void free_vcpu_struct(struct vcpu *v);
-extern void arch_do_createdomain(struct vcpu *v);
+extern int arch_do_createdomain(struct vcpu *v);
-extern int arch_set_info_guest(
+extern int arch_set_info_guest(
struct vcpu *v, struct vcpu_guest_context *c);
extern void vcpu_migrate_cpu(struct vcpu *v, int newcpu);
diff --git a/xen/include/xen/iocap.h b/xen/include/xen/iocap.h
new file mode 100644
index 0000000000..967f70fe4b
--- /dev/null
+++ b/xen/include/xen/iocap.h
@@ -0,0 +1,13 @@
+/******************************************************************************
+ * iocap.h
+ *
+ * Per-domain I/O capabilities.
+ */
+
+#ifndef __XEN_IOCAP_H__
+#define __XEN_IOCAP_H__
+
+#include <xen/rangeset.h>
+#include <asm/iocap.h>
+
+#endif /* __XEN_IOCAP_H__ */