diff options
-rw-r--r-- | xen/arch/ia64/xen/domain.c | 6 | ||||
-rw-r--r-- | xen/arch/x86/dom0_ops.c | 20 | ||||
-rw-r--r-- | xen/arch/x86/domain.c | 29 | ||||
-rw-r--r-- | xen/arch/x86/domain_build.c | 25 | ||||
-rw-r--r-- | xen/arch/x86/physdev.c | 26 | ||||
-rw-r--r-- | xen/arch/x86/setup.c | 5 | ||||
-rw-r--r-- | xen/arch/x86/traps.c | 13 | ||||
-rw-r--r-- | xen/common/domain.c | 27 | ||||
-rw-r--r-- | xen/common/rangeset.c | 2 | ||||
-rw-r--r-- | xen/drivers/char/ns16550.c | 4 | ||||
-rw-r--r-- | xen/include/asm-ia64/domain.h | 2 | ||||
-rw-r--r-- | xen/include/asm-ia64/iocap.h | 10 | ||||
-rw-r--r-- | xen/include/asm-x86/domain.h | 4 | ||||
-rw-r--r-- | xen/include/asm-x86/iocap.h | 17 | ||||
-rw-r--r-- | xen/include/asm-x86/physdev.h | 17 | ||||
-rw-r--r-- | xen/include/xen/domain.h | 4 | ||||
-rw-r--r-- | xen/include/xen/iocap.h | 13 |
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__ */ |