diff options
author | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-08-19 15:39:07 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk> | 2004-08-19 15:39:07 +0000 |
commit | e23d7726d5aebf24e119fcd33b3438ed64c74a4b (patch) | |
tree | 1ccd638b7211fe7033578a0880869dde06b4b7c0 | |
parent | 8e9f7aa2977967bce51c83adf16e48ad6f378dfc (diff) | |
download | xen-e23d7726d5aebf24e119fcd33b3438ed64c74a4b.tar.gz xen-e23d7726d5aebf24e119fcd33b3438ed64c74a4b.tar.bz2 xen-e23d7726d5aebf24e119fcd33b3438ed64c74a4b.zip |
bitkeeper revision 1.1159.44.1 (4124c99bzYQ86nF2sa6s-nSiOfibyQ)
Clean up mapping of I/O memory and Xen-heap memory. We define two
'dummy domains' for this purpose which can be specified to
MMUEXT_SET_FOREIGNDOM.
-rw-r--r-- | linux-2.4.26-xen-sparse/arch/xen/mm/ioremap.c | 15 | ||||
-rw-r--r-- | linux-2.4.26-xen-sparse/drivers/char/mem.c | 3 | ||||
-rw-r--r-- | linux-2.6.7-xen-sparse/arch/xen/i386/mm/ioremap.c | 15 | ||||
-rw-r--r-- | linux-2.6.7-xen-sparse/drivers/char/mem.c | 3 | ||||
-rw-r--r-- | linux-2.6.7-xen-sparse/drivers/xen/privcmd/privcmd.c | 15 | ||||
-rw-r--r-- | tools/libxc/xc.h | 2 | ||||
-rw-r--r-- | tools/libxc/xc_linux_save.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/memory.c | 81 | ||||
-rw-r--r-- | xen/arch/x86/setup.c | 3 | ||||
-rw-r--r-- | xen/common/dom0_ops.c | 9 | ||||
-rw-r--r-- | xen/common/domain.c | 17 | ||||
-rw-r--r-- | xen/common/kernel.c | 3 | ||||
-rw-r--r-- | xen/common/memory.c | 19 | ||||
-rw-r--r-- | xen/common/page_alloc.c | 2 | ||||
-rw-r--r-- | xen/include/asm-x86/mm.h | 2 | ||||
-rw-r--r-- | xen/include/hypervisor-ifs/hypervisor-if.h | 33 | ||||
-rw-r--r-- | xen/include/xen/sched.h | 15 |
17 files changed, 152 insertions, 87 deletions
diff --git a/linux-2.4.26-xen-sparse/arch/xen/mm/ioremap.c b/linux-2.4.26-xen-sparse/arch/xen/mm/ioremap.c index 9cd34cd925..34c95c84b5 100644 --- a/linux-2.4.26-xen-sparse/arch/xen/mm/ioremap.c +++ b/linux-2.4.26-xen-sparse/arch/xen/mm/ioremap.c @@ -115,17 +115,10 @@ int direct_remap_area_pages(struct mm_struct *mm, #define MAX_DIRECTMAP_MMU_QUEUE 130 mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *w, *v; - if ( domid != 0 ) - { - u[0].ptr = MMU_EXTENDED_COMMAND; - u[0].val = MMUEXT_SET_FOREIGNDOM; - u[0].val |= (unsigned long)domid << 16; - v = w = &u[1]; - } - else - { - v = w = &u[0]; - } + u[0].ptr = MMU_EXTENDED_COMMAND; + u[0].val = MMUEXT_SET_FOREIGNDOM; + u[0].val |= (unsigned long)domid << 16; + v = w = &u[1]; start_address = address; diff --git a/linux-2.4.26-xen-sparse/drivers/char/mem.c b/linux-2.4.26-xen-sparse/drivers/char/mem.c index 5635b269aa..f0d8502190 100644 --- a/linux-2.4.26-xen-sparse/drivers/char/mem.c +++ b/linux-2.4.26-xen-sparse/drivers/char/mem.c @@ -237,6 +237,9 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) if (!(start_info.flags & SIF_PRIVILEGED)) return -ENXIO; + if (file->private_data == NULL) + file->private_data = (void *)(unsigned long)DOMID_IO; + /* DONTCOPY is essential for Xen as copy_page_range is broken. */ vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); diff --git a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/ioremap.c b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/ioremap.c index e6d1e95cb4..3fb6ea9aa0 100644 --- a/linux-2.6.7-xen-sparse/arch/xen/i386/mm/ioremap.c +++ b/linux-2.6.7-xen-sparse/arch/xen/i386/mm/ioremap.c @@ -415,17 +415,10 @@ int direct_remap_area_pages(struct mm_struct *mm, #define MAX_DIRECTMAP_MMU_QUEUE 130 mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *w, *v; - if ( domid != 0 ) - { - u[0].ptr = MMU_EXTENDED_COMMAND; - u[0].val = MMUEXT_SET_FOREIGNDOM; - u[0].val |= (unsigned long)domid << 16; - v = w = &u[1]; - } - else - { - v = w = &u[0]; - } + u[0].ptr = MMU_EXTENDED_COMMAND; + u[0].val = MMUEXT_SET_FOREIGNDOM; + u[0].val |= (unsigned long)domid << 16; + v = w = &u[1]; start_address = address; diff --git a/linux-2.6.7-xen-sparse/drivers/char/mem.c b/linux-2.6.7-xen-sparse/drivers/char/mem.c index ceea2b5ffd..ed3df13f65 100644 --- a/linux-2.6.7-xen-sparse/drivers/char/mem.c +++ b/linux-2.6.7-xen-sparse/drivers/char/mem.c @@ -247,6 +247,9 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma) if (!(start_info.flags & SIF_PRIVILEGED)) return -ENXIO; + if (file->private_data == NULL) + file->private_data = (void *)(unsigned long)DOMID_IO; + /* DONTCOPY is essential for Xen as copy_page_range is broken. */ vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); diff --git a/linux-2.6.7-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6.7-xen-sparse/drivers/xen/privcmd/privcmd.c index aa7a1d9a01..c57bdf6b23 100644 --- a/linux-2.6.7-xen-sparse/drivers/xen/privcmd/privcmd.c +++ b/linux-2.6.7-xen-sparse/drivers/xen/privcmd/privcmd.c @@ -138,17 +138,10 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, if ( (m.addr + (m.num<<PAGE_SHIFT)) > vma->vm_end ) { ret = -EFAULT; goto batch_err; } - if ( m.dom != 0 ) - { - u[0].ptr = MMU_EXTENDED_COMMAND; - u[0].val = MMUEXT_SET_FOREIGNDOM; - u[0].val |= (unsigned long)m.dom << 16; - v = w = &u[1]; - } - else - { - v = w = &u[0]; - } + u[0].ptr = MMU_EXTENDED_COMMAND; + u[0].val = MMUEXT_SET_FOREIGNDOM; + u[0].val |= (unsigned long)m.dom << 16; + v = w = &u[1]; p = m.arr; addr = m.addr; diff --git a/tools/libxc/xc.h b/tools/libxc/xc.h index 974ac975f2..8b54ed0207 100644 --- a/tools/libxc/xc.h +++ b/tools/libxc/xc.h @@ -154,6 +154,8 @@ int xc_rrobin_global_set(int xc_handle, u64 slice); int xc_rrobin_global_get(int xc_handle, u64 *slice); #define DOMID_SELF (0x7FF0U) +#define DOMID_IO (0x7FF1U) +#define DOMID_XEN (0x7FF2U) typedef struct { #define EVTCHNSTAT_closed 0 /* Chennel is not in use. */ diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index 5a47b30f56..def9f7516d 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -423,7 +423,7 @@ int xc_linux_save(int xc_handle, XcIOContext *ioctxt) mfn_to_pfn_table_start_mfn = xc_get_m2p_start_mfn( xc_handle ); live_mfn_to_pfn_table = - mfn_mapper_map_single(xc_handle, 0x7FFFU, + mfn_mapper_map_single(xc_handle, DOMID_XEN, PAGE_SIZE*1024, PROT_READ, mfn_to_pfn_table_start_mfn ); diff --git a/xen/arch/x86/memory.c b/xen/arch/x86/memory.c index cb0cf2f19a..5152e39648 100644 --- a/xen/arch/x86/memory.c +++ b/xen/arch/x86/memory.c @@ -137,14 +137,49 @@ static struct { */ #define FOREIGNDOM (percpu_info[smp_processor_id()].foreign ? : current) -void ptwr_init_backpointers(void); +/* Private domain structs for DOMID_XEN and DOMID_IO. */ +static struct domain *dom_xen, *dom_io; void arch_init_memory(void) { + static void ptwr_init_backpointers(void); + unsigned long mfn; + memset(percpu_info, 0, sizeof(percpu_info)); vm_assist_info[VMASST_TYPE_writeable_pagetables].enable = ptwr_init_backpointers; + + /* Initialise to a magic of 0x55555555 so easier to spot bugs later. */ + memset(machine_to_phys_mapping, 0x55, 4<<20); + + /* + * Initialise our DOMID_XEN domain. + * Any Xen-heap pages that we will allow to be mapped will have + * their domain field set to dom_xen. + */ + dom_xen = alloc_domain_struct(); + atomic_set(&dom_xen->refcnt, 1); + dom_xen->domain = DOMID_XEN; + + /* + * Initialise our DOMID_IO domain. + * This domain owns no pages but is considered a special case when + * mapping I/O pages, as the mappings occur at the priv of the caller. + */ + dom_io = alloc_domain_struct(); + atomic_set(&dom_io->refcnt, 1); + dom_io->domain = DOMID_IO; + + /* M2P table is mappable read-only by privileged domains. */ + for ( mfn = virt_to_phys(&machine_to_phys_mapping[0<<20])>>PAGE_SHIFT; + mfn < virt_to_phys(&machine_to_phys_mapping[1<<20])>>PAGE_SHIFT; + mfn++ ) + { + frame_table[mfn].u.inuse.count_info = 1 | PGC_allocated; + frame_table[mfn].u.inuse.type_info = 1 | PGT_gdt_page; /* non-RW */ + frame_table[mfn].u.inuse.domain = dom_xen; + } } static void __invalidate_shadow_ldt(struct domain *d) @@ -178,7 +213,7 @@ static inline void invalidate_shadow_ldt(struct domain *d) } -int alloc_segdesc_page(struct pfn_info *page) +static int alloc_segdesc_page(struct pfn_info *page) { unsigned long *descs = map_domain_mem((page-frame_table) << PAGE_SHIFT); int i; @@ -345,11 +380,15 @@ get_page_from_l1e( if ( unlikely(!pfn_is_ram(pfn)) ) { - if ( IS_PRIV(current) ) + /* Revert to caller privileges if FD == DOMID_IO. */ + if ( d == dom_io ) + d = current; + + if ( IS_PRIV(d) ) return 1; - if ( IS_CAPABLE_PHYSDEV(current) ) - return domain_iomem_in_pfn(current, pfn); + if ( IS_CAPABLE_PHYSDEV(d) ) + return domain_iomem_in_pfn(d, pfn); MEM_LOG("Non-privileged attempt to map I/O space %08lx", pfn); return 0; @@ -827,9 +866,16 @@ static int do_extended_command(unsigned long ptr, unsigned long val) if ( !IS_PRIV(d) ) { - MEM_LOG("Dom %u has no privilege to set subject domain", - d->domain); - okay = 0; + switch ( domid ) + { + case DOMID_IO: + get_knownalive_domain(e = dom_io); + break; + default: + MEM_LOG("Dom %u cannot set foreign dom\n", d->domain); + okay = 0; + break; + } } else { @@ -839,8 +885,19 @@ static int do_extended_command(unsigned long ptr, unsigned long val) percpu_info[cpu].foreign = e = find_domain_by_id(domid); if ( e == NULL ) { - MEM_LOG("Unknown domain '%u'", domid); - okay = 0; + switch ( domid ) + { + case DOMID_XEN: + get_knownalive_domain(e = dom_xen); + break; + case DOMID_IO: + get_knownalive_domain(e = dom_io); + break; + default: + MEM_LOG("Unknown domain '%u'", domid); + okay = 0; + break; + } } } break; @@ -926,7 +983,7 @@ static int do_extended_command(unsigned long ptr, unsigned long val) * the lock so they'll spin waiting for us. */ if ( unlikely(e->tot_pages++ == 0) ) - get_domain(e); + get_knownalive_domain(e); list_add_tail(&page->list, &e->page_list); reassign_fail: @@ -1493,7 +1550,7 @@ int ptwr_do_page_fault(unsigned long addr) return 0; } -void ptwr_init_backpointers(void) +static void ptwr_init_backpointers(void) { struct pfn_info *page; unsigned long pde; diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index e629930ab6..3d18ebd4ee 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -16,6 +16,7 @@ #include <asm/domain_page.h> #include <asm/pdb.h> +extern void arch_init_memory(void); extern void init_IRQ(void); extern void trap_init(void); extern void time_init(void); @@ -360,6 +361,8 @@ void __init start_of_day(void) time_init(); /* installs software handler for HZ clock. */ init_apic_mappings(); /* make APICs addressable in our pagetables. */ + arch_init_memory(); + #ifndef CONFIG_SMP APIC_init_uniprocessor(); #else diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 6c8abcb8f8..1f1e911b73 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -25,13 +25,14 @@ extern unsigned int alloc_new_dom_mem(struct domain *, unsigned int); extern long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op); -extern void arch_getdomaininfo_ctxt(struct domain *, full_execution_context_t *); +extern void arch_getdomaininfo_ctxt( + struct domain *, full_execution_context_t *); static inline int is_free_domid(domid_t dom) { struct domain *d; - if ( dom >= DOMID_SELF ) + if ( dom >= DOMID_FIRST_RESERVED ) return 0; if ( (d = find_domain_by_id(dom)) == NULL ) @@ -66,7 +67,7 @@ static int allocate_domid(domid_t *pdom) } /* Couldn't find a free domain id in 0..topdom, try higher. */ - for ( dom = topdom; dom < DOMID_SELF; dom++ ) + for ( dom = topdom; dom < DOMID_FIRST_RESERVED; dom++ ) { if ( is_free_domid(dom) ) { @@ -167,7 +168,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) domid_t dom; dom = op->u.createdomain.domain; - if ( (dom > 0) && (dom < DOMID_SELF) ) + if ( (dom > 0) && (dom < DOMID_FIRST_RESERVED) ) { ret = -EINVAL; if ( !is_free_domid(dom) ) diff --git a/xen/common/domain.c b/xen/common/domain.c index cac4c2edf0..4ca9f58135 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -39,11 +39,18 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) d->domain = dom_id; d->processor = cpu; d->create_time = NOW(); - /* Initialise the sleep_lock */ spin_lock_init(&d->sleep_lock); memcpy(&d->thread, &idle0_task.thread, sizeof(d->thread)); + spin_lock_init(&d->page_alloc_lock); + INIT_LIST_HEAD(&d->page_list); + d->max_pages = d->tot_pages = 0; + + /* Per-domain PCI-device list. */ + spin_lock_init(&d->pcidev_lock); + INIT_LIST_HEAD(&d->pcidev_list); + if ( d->domain != IDLE_DOMAIN_ID ) { if ( init_event_channels(d) != 0 ) @@ -59,16 +66,8 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu) d->addr_limit = USER_DS; - spin_lock_init(&d->page_alloc_lock); - INIT_LIST_HEAD(&d->page_list); - d->max_pages = d->tot_pages = 0; - arch_do_createdomain(d); - /* Per-domain PCI-device list. */ - spin_lock_init(&d->pcidev_lock); - INIT_LIST_HEAD(&d->pcidev_list); - sched_add_domain(d); write_lock_irqsave(&tasklist_lock, flags); diff --git a/xen/common/kernel.c b/xen/common/kernel.c index d4cd43ae9d..707cede7f1 100644 --- a/xen/common/kernel.c +++ b/xen/common/kernel.c @@ -304,9 +304,6 @@ void cmain(multiboot_info_t *mbi) start_of_day(); - /* Add CPU0 idle task to the task hash list */ - task_hash[TASK_HASH(IDLE_DOMAIN_ID)] = &idle0_task; - /* Create initial domain 0. */ new_dom = do_createdomain(0, 0); if ( new_dom == NULL ) diff --git a/xen/common/memory.c b/xen/common/memory.c index 8e513b55e3..2dfdd10e07 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -37,14 +37,8 @@ struct pfn_info *frame_table; unsigned long frame_table_size; unsigned long max_page; -extern void arch_init_memory(void); - void __init init_frametable(void *frametable_vstart, unsigned long nr_pages) { - unsigned long mfn; - - arch_init_memory(); - max_page = nr_pages; frame_table_size = nr_pages * sizeof(struct pfn_info); frame_table_size = (frame_table_size + PAGE_SIZE - 1) & PAGE_MASK; @@ -54,17 +48,4 @@ void __init init_frametable(void *frametable_vstart, unsigned long nr_pages) panic("Not enough memory for frame table - reduce Xen heap size?\n"); memset(frame_table, 0, frame_table_size); - - /* Initialise to a magic of 0x55555555 so easier to spot bugs later. */ - memset(machine_to_phys_mapping, 0x55, 4<<20); - - /* Pin the ownership of the MP table so that DOM0 can map it later. */ - for ( mfn = virt_to_phys(&machine_to_phys_mapping[0<<20])>>PAGE_SHIFT; - mfn < virt_to_phys(&machine_to_phys_mapping[1<<20])>>PAGE_SHIFT; - mfn++ ) - { - frame_table[mfn].u.inuse.count_info = 1 | PGC_allocated; - frame_table[mfn].u.inuse.type_info = 1 | PGT_gdt_page; /* non-RW */ - frame_table[mfn].u.inuse.domain = &idle0_task; - } } diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index b3b056fd68..323ecd244e 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -393,7 +393,7 @@ struct pfn_info *alloc_domheap_pages(struct domain *d, int order) } if ( unlikely(d->tot_pages == 0) ) - get_domain(d); + get_knownalive_domain(d); d->tot_pages += 1 << order; diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index c0143352e0..a2fc40e0b3 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -108,7 +108,7 @@ struct pfn_info /* _dom holds an allocation reference */ \ (_pfn)->u.inuse.count_info = PGC_allocated | 1; \ if ( unlikely((_dom)->xenheap_pages++ == 0) ) \ - get_domain(_dom); \ + get_knownalive_domain(_dom); \ spin_unlock(&(_dom)->page_alloc_lock); \ } while ( 0 ) diff --git a/xen/include/hypervisor-ifs/hypervisor-if.h b/xen/include/hypervisor-ifs/hypervisor-if.h index 1c28062c5b..efcaeb8abb 100644 --- a/xen/include/hypervisor-ifs/hypervisor-if.h +++ b/xen/include/hypervisor-ifs/hypervisor-if.h @@ -87,8 +87,10 @@ * ptr[1:0] == MMU_NORMAL_PT_UPDATE: * Updates an entry in a page table. If updating an L1 table, and the new * table entry is valid/present, the mapped frame must belong to the FD, if - * an FD has been specified. If attempting to map an I/O page, then the FD - * is ignored, but the calling domain must have sufficient privilege. + * an FD has been specified. If attempting to map an I/O page then the + * caller assumes the privilege of the FD. + * FD == DOMID_IO: Permit /only/ I/O mappings, at the priv level of the caller. + * FD == DOMID_XEN: Map restricted areas of Xen's heap space. * ptr[:2] -- Machine address of the page-table entry to modify. * val -- Value to write. * @@ -121,6 +123,7 @@ * val[7:0] == MMUEXT_SET_FOREIGNDOM: * val[31:15] -- Domain to set as the Foreign Domain (FD). * (NB. DOMID_SELF is not recognised) + * If FD != DOMID_IO then the caller must be privileged. * * val[7:0] == MMUEXT_REASSIGN_PAGE: * ptr[:2] -- A machine address within the page to be reassigned to the FD. @@ -186,9 +189,31 @@ #ifndef __ASSEMBLY__ typedef u16 domid_t; + +/* Domain ids >= DOMID_FIRST_RESERVED cannot be used for ordinary domains. */ +#define DOMID_FIRST_RESERVED (0x7FF0U) + /* DOMID_SELF is used in certain contexts to refer to oneself. */ -#define DOMID_SELF (0x7FF0U) -/* NB. IDs >= 0x7FF1 are reserved for future use. */ +#define DOMID_SELF (0x7FF0U) + +/* + * DOMID_IO is used to restrict page-table updates to mapping I/O memory. + * Although no Foreign Domain need be specified to map I/O pages, DOMID_IO + * is useful to ensure that no mappings to the OS's own heap are accidentally + * installed. (e.g., in Linux this could cause havoc as reference counts + * aren't adjusted on the I/O-mapping code path). + * This only makes sense in MMUEXT_SET_FOREIGNDOM, but in that context can + * be specified by any calling domain. + */ +#define DOMID_IO (0x7FF1U) + +/* + * DOMID_XEN is used to allow privileged domains to map restricted parts of + * Xen's heap space (e.g., the machine_to_phys table). + * This only makes sense in MMUEXT_SET_FOREIGNDOM, and is only permitted if + * the caller is privileged. + */ +#define DOMID_XEN (0x7FF2U) /* * Send an array of these to HYPERVISOR_mmu_update(). diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index 06b6faf6cc..af74cf5380 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -164,11 +164,26 @@ struct domain *alloc_domain_struct(); #define DOMAIN_DESTRUCTED (1<<31) /* assumes atomic_t is >= 32 bits */ #define put_domain(_d) \ if ( atomic_dec_and_test(&(_d)->refcnt) ) domain_destruct(_d) + +/* + * Use this when you don't have an existing reference to @d. It returns + * FALSE if @d is being destructed. + */ static inline int get_domain(struct domain *d) { atomic_inc(&d->refcnt); return !(atomic_read(&d->refcnt) & DOMAIN_DESTRUCTED); } + +/* + * Use this when you already have, or are borrowing, a reference to @d. + * In this case we know that @d cannot be destructed under our feet. + */ +static inline void get_knownalive_domain(struct domain *d) +{ + atomic_inc(&d->refcnt); + ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTRUCTED)); +} extern struct domain *do_createdomain( domid_t dom_id, unsigned int cpu); |