diff options
-rw-r--r-- | .hgignore | 20 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c | 8 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/drivers/xen/blkback/interface.c | 4 | ||||
-rw-r--r-- | linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 6 | ||||
-rw-r--r-- | tools/libxc/xc_core.c | 7 | ||||
-rw-r--r-- | tools/libxc/xc_gnttab.c | 4 | ||||
-rw-r--r-- | tools/libxc/xc_linux_build.c | 15 | ||||
-rw-r--r-- | tools/libxc/xc_linux_restore.c | 11 | ||||
-rw-r--r-- | tools/libxc/xc_linux_save.c | 27 | ||||
-rw-r--r-- | tools/libxc/xc_load_elf.c | 3 | ||||
-rw-r--r-- | tools/libxc/xc_ptrace.c | 2 | ||||
-rw-r--r-- | tools/libxc/xc_vmx_build.c | 14 | ||||
-rw-r--r-- | tools/python/xen/xend/XendDomainInfo.py | 4 | ||||
-rwxr-xr-x | tools/python/xen/xend/server/controller.py | 8 | ||||
-rw-r--r-- | tools/xenstore/xenstored_core.c | 7 | ||||
-rw-r--r-- | xen/arch/ia64/grant_table.c | 4 | ||||
-rw-r--r-- | xen/arch/x86/mm.c | 231 | ||||
-rw-r--r-- | xen/arch/x86/setup.c | 25 | ||||
-rw-r--r-- | xen/common/grant_table.c | 133 | ||||
-rw-r--r-- | xen/include/asm-x86/mm.h | 9 | ||||
-rw-r--r-- | xen/include/public/grant_table.h | 23 | ||||
-rw-r--r-- | xen/include/xen/grant_table.h | 7 |
22 files changed, 402 insertions, 170 deletions
@@ -69,19 +69,19 @@ ^tools/blktap/blkdump$ ^tools/blktap/blkgnbd$ ^tools/blktap/blkimg$ -^tools/blktap/blockstore\.dat$ -^tools/blktap/blockstored$ ^tools/blktap/bstest$ -^tools/blktap/parallax$ ^tools/blktap/vdi\.dot$ ^tools/blktap/vdi\.ps$ -^tools/blktap/vdi_create$ -^tools/blktap/vdi_fill$ -^tools/blktap/vdi_list$ -^tools/blktap/vdi_snap$ -^tools/blktap/vdi_snap_list$ -^tools/blktap/vdi_tree$ -^tools/blktap/vdi_validate$ +^tools/blktap/parallax/vdi_create$ +^tools/blktap/parallax/vdi_fill$ +^tools/blktap/parallax/vdi_list$ +^tools/blktap/parallax/vdi_snap$ +^tools/blktap/parallax/vdi_snap_list$ +^tools/blktap/parallax/vdi_snap_delete$ +^tools/blktap/parallax/vdi_tree$ +^tools/blktap/parallax/vdi_validate$ +^tools/blktap/parallax/parallax$ +^tools/blktap/parallax/blockstored$ ^tools/blktap/xen/.*$ ^tools/check/\..*$ ^tools/cmdline/.*$ diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c index 1121aeb56b..eb26470286 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c @@ -120,10 +120,10 @@ static void fast_flush_area(int idx, int nr_pages) { if ( BLKBACK_INVALID_HANDLE != ( handle = pending_handle(idx, i) ) ) { - unmap[i].host_virt_addr = MMAP_VADDR(idx, i); + unmap[i].host_addr = MMAP_VADDR(idx, i); unmap[i].dev_bus_addr = 0; unmap[i].handle = handle; - pending_handle(idx, i) = BLKBACK_INVALID_HANDLE; + pending_handle(idx, i) = BLKBACK_INVALID_HANDLE; invcount++; } } @@ -383,7 +383,7 @@ static void dispatch_probe(blkif_t *blkif, blkif_request_t *req) { struct gnttab_map_grant_ref map; - map.host_virt_addr = MMAP_VADDR(pending_idx, 0); + map.host_addr = MMAP_VADDR(pending_idx, 0); map.flags = GNTMAP_host_map; map.ref = blkif_gref_from_fas(req->frame_and_sects[0]); map.dom = blkif->domid; @@ -480,7 +480,7 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req) goto bad_descriptor; preq.nr_sects += seg[i].nsec; - map[i].host_virt_addr = MMAP_VADDR(pending_idx, i); + map[i].host_addr = MMAP_VADDR(pending_idx, i); map[i].dom = blkif->domid; map[i].ref = blkif_gref_from_fas(fas); map[i].flags = GNTMAP_host_map; diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c index b62c2d345d..14de83c92f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c @@ -42,7 +42,7 @@ static void __blkif_disconnect_complete(void *arg) * must still be notified to the remote driver. */ #ifdef CONFIG_XEN_BLKDEV_GRANT - op.host_virt_addr = blkif->shmem_vaddr; + op.host_addr = blkif->shmem_vaddr; op.handle = blkif->shmem_handle; op.dev_bus_addr = 0; BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)); @@ -204,7 +204,7 @@ void blkif_connect(blkif_be_connect_t *connect) #else { /* Map: Use the Grant table reference */ struct gnttab_map_grant_ref op; - op.host_virt_addr = VMALLOC_VMADDR(vma->addr); + op.host_addr = VMALLOC_VMADDR(vma->addr); op.flags = GNTMAP_host_map; op.ref = ref; op.dom = domid; diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c index edc6c67d1f..8be345edea 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -511,9 +511,9 @@ inline static void net_tx_action_dealloc(void) gop = unmap_ops; while (dc != dp) { pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)]; - gop->host_virt_addr = MMAP_VADDR(pending_idx); + gop->host_addr = MMAP_VADDR(pending_idx); gop->dev_bus_addr = 0; - gop->handle = grant_tx_ref[pending_idx]; + gop->handle = grant_tx_ref[pending_idx]; grant_tx_ref[pending_idx] = GRANT_INVALID_REF; gop++; } @@ -699,7 +699,7 @@ static void net_tx_action(unsigned long unused) /* Packets passed to netif_rx() must have some headroom. */ skb_reserve(skb, 16); #ifdef CONFIG_XEN_NETDEV_GRANT_TX - mop->host_virt_addr = MMAP_VADDR(pending_idx); + mop->host_addr = MMAP_VADDR(pending_idx); mop->dom = netif->domid; mop->ref = txreq.addr >> PAGE_SHIFT; mop->flags = GNTMAP_host_map | GNTMAP_readonly; diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c index 653512ab92..df4352de1c 100644 --- a/tools/libxc/xc_core.c +++ b/tools/libxc/xc_core.c @@ -43,7 +43,7 @@ xc_domain_dumpcore(int xc_handle, goto error_out; } - if ((dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == 0) { + if ((dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL) { PERROR("Could not allocate dump_mem"); goto error_out; } @@ -108,9 +108,8 @@ xc_domain_dumpcore(int xc_handle, free(dump_mem_start); return 0; error_out: - if (dump_fd) + if (dump_fd != -1) close(dump_fd); - if (dump_mem_start) - free(dump_mem_start); + free(dump_mem_start); return -1; } diff --git a/tools/libxc/xc_gnttab.c b/tools/libxc/xc_gnttab.c index 4101ca74dd..83fcf9218c 100644 --- a/tools/libxc/xc_gnttab.c +++ b/tools/libxc/xc_gnttab.c @@ -50,7 +50,7 @@ int xc_gnttab_map_grant_ref(int xc_handle, struct gnttab_map_grant_ref op; int rc; - op.host_virt_addr = host_virt_addr; + op.host_addr = host_virt_addr; op.dom = (domid_t)dom; op.ref = ref; op.flags = flags; @@ -75,7 +75,7 @@ int xc_gnttab_unmap_grant_ref(int xc_handle, struct gnttab_unmap_grant_ref op; int rc; - op.host_virt_addr = host_virt_addr; + op.host_addr = host_virt_addr; op.dev_bus_addr = dev_bus_addr; op.handle = handle; diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 48cace5647..45044c0735 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -318,8 +318,7 @@ static int setup_guest(int xc_handle, return 0; error_out: - if ( page_array != NULL ) - free(page_array); + free(page_array); return -1; } #else /* x86 */ @@ -616,10 +615,8 @@ static int setup_guest(int xc_handle, return 0; error_out: - if ( mmu != NULL ) - free(mmu); - if ( page_array != NULL ) - free(page_array); + free(mmu); + free(page_array); return -1; } #endif @@ -719,8 +716,7 @@ int xc_linux_build(int xc_handle, close(initrd_fd); if ( initrd_gfd ) gzclose(initrd_gfd); - if ( image != NULL ) - free(image); + free(image); #ifdef __ia64__ /* based on new_thread in xen/arch/ia64/domain.c */ @@ -806,8 +802,7 @@ int xc_linux_build(int xc_handle, gzclose(initrd_gfd); else if ( initrd_fd >= 0 ) close(initrd_fd); - if ( image != NULL ) - free(image); + free(image); return -1; } diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index c2bce43910..67d5607e77 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -32,7 +32,7 @@ #define PPRINTF(_f, _a...) #endif -ssize_t +static ssize_t read_exact(int fd, void *buf, size_t count) { int r = 0, s; @@ -607,12 +607,9 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns, out: if ( (rc != 0) && (dom != 0) ) xc_domain_destroy(xc_handle, dom); - if ( mmu != NULL ) - free(mmu); - if ( pfn_to_mfn_table != NULL ) - free(pfn_to_mfn_table); - if ( pfn_type != NULL ) - free(pfn_type); + free(mmu); + free(pfn_to_mfn_table); + free(pfn_type); DPRINTF("Restore exit with rc=%d\n", rc); return rc; diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index c2a6af5f13..77349c88a3 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -136,7 +136,7 @@ static long long tv_to_us( struct timeval *new ) return (new->tv_sec * 1000000) + new->tv_usec; } -static long long llgettimeofday() +static long long llgettimeofday( void ) { struct timeval now; gettimeofday(&now, NULL); @@ -312,9 +312,9 @@ static int analysis_phase( int xc_handle, u32 domid, } -int suspend_and_state(int xc_handle, int io_fd, int dom, - xc_dominfo_t *info, - vcpu_guest_context_t *ctxt) +static int suspend_and_state(int xc_handle, int io_fd, int dom, + xc_dominfo_t *info, + vcpu_guest_context_t *ctxt) { int i=0; char ans[30]; @@ -1051,20 +1051,11 @@ int xc_linux_save(int xc_handle, int io_fd, u32 dom) if(live_mfn_to_pfn_table) munmap(live_mfn_to_pfn_table, PAGE_SIZE*1024); - if (pfn_type != NULL) - free(pfn_type); - - if (pfn_batch != NULL) - free(pfn_batch); - - if (to_send != NULL) - free(to_send); - - if (to_fix != NULL) - free(to_fix); - - if (to_skip != NULL) - free(to_skip); + free(pfn_type); + free(pfn_batch); + free(to_send); + free(to_fix); + free(to_skip); DPRINTF("Save exit rc=%d\n",rc); return !!rc; diff --git a/tools/libxc/xc_load_elf.c b/tools/libxc/xc_load_elf.c index 926db3a964..90417fb2ca 100644 --- a/tools/libxc/xc_load_elf.c +++ b/tools/libxc/xc_load_elf.c @@ -309,8 +309,7 @@ loadelfsymtab( dsi->v_end = round_pgup(maxva); out: - if ( p != NULL ) - free(p); + free(p); return 0; } diff --git a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c index 2b53f460cf..fdeca60e2e 100644 --- a/tools/libxc/xc_ptrace.c +++ b/tools/libxc/xc_ptrace.c @@ -221,7 +221,7 @@ map_domain_va(unsigned long domid, int cpu, void * guest_va, int perm) return (void *)(((unsigned long)page_virt[cpu]) | (va & BSD_PAGE_MASK)); error_out: - return 0; + return NULL; } int diff --git a/tools/libxc/xc_vmx_build.c b/tools/libxc/xc_vmx_build.c index 9836746919..f10cc8391c 100644 --- a/tools/libxc/xc_vmx_build.c +++ b/tools/libxc/xc_vmx_build.c @@ -616,17 +616,15 @@ static int setup_guest(int xc_handle, return 0; error_out: - if ( mmu != NULL ) - free(mmu); - if ( page_array != NULL ) - free(page_array); + free(mmu); + free(page_array); return -1; } #define VMX_FEATURE_FLAG 0x20 -int vmx_identify(void) +static int vmx_identify(void) { int eax, ecx; @@ -745,8 +743,7 @@ int xc_vmx_build(int xc_handle, close(initrd_fd); if ( initrd_gfd ) gzclose(initrd_gfd); - if ( image != NULL ) - free(image); + free(image); ctxt->flags = VGCF_VMX_GUEST; /* FPU is set up to default initial state. */ @@ -801,8 +798,7 @@ int xc_vmx_build(int xc_handle, gzclose(initrd_gfd); else if ( initrd_fd >= 0 ) close(initrd_fd); - if ( image != NULL ) - free(image); + free(image); return -1; } diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 4e01041342..029021f13e 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -138,7 +138,7 @@ def dom_get(dom): if domlist and dom == domlist[0]['dom']: return domlist[0] return None - + class XendDomainInfo: """Virtual machine object.""" @@ -754,7 +754,7 @@ class XendDomainInfo: @param dev_config: device configuration """ dev_type = sxp.name(dev_config) - dev = self.createDevice(self, dev_config, change=True) + dev = self.createDevice(dev_type, dev_config, change=True) self.config.append(['device', dev.getConfig()]) return dev.sxpr() diff --git a/tools/python/xen/xend/server/controller.py b/tools/python/xen/xend/server/controller.py index f399503d7f..973398f090 100755 --- a/tools/python/xen/xend/server/controller.py +++ b/tools/python/xen/xend/server/controller.py @@ -142,7 +142,7 @@ class DevControllerTable: def createDevController(self, type, vm, recreate=False): cls = self.getDevControllerClass(type) if not cls: - raise XendError("unknown device type: " + type) + raise XendError("unknown device type: " + str(type)) return cls.createDevController(vm, recreate=recreate) def getDevControllerTable(): @@ -283,6 +283,8 @@ class DevController: dev.attach(recreate=recreate, change=change) dev.exportToDB() + return dev + def configureDevice(self, id, config, change=False): """Reconfigure an existing device. May be defined in subclass.""" @@ -323,9 +325,9 @@ class DevController: return self.destroyed def getDevice(self, id, error=False): - dev = self.devices.get(id) + dev = self.devices.get(int(id)) if error and not dev: - raise XendError("invalid device id: " + id) + raise XendError("invalid device id: " + str(id)) return dev def getDeviceIds(self): diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index c91021876b..02f480e220 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -1587,7 +1587,7 @@ static struct option options[] = { { "no-fork", 0, NULL, 'N' }, int main(int argc, char *argv[]) { - int opt, *sock, *ro_sock, event_fd, max, tmpout; + int opt, *sock, *ro_sock, event_fd, max; struct sockaddr_un addr; fd_set inset, outset; bool dofork = true; @@ -1673,9 +1673,8 @@ int main(int argc, char *argv[]) restore_existing_connections(); if (outputpid) { - char buffer[20]; - sprintf(buffer, "%i\n", getpid()); - write(tmpout, buffer, strlen(buffer)); + printf("%i\n", getpid()); + fflush(stdout); } /* close stdin/stdout now we're ready to accept connections */ diff --git a/xen/arch/ia64/grant_table.c b/xen/arch/ia64/grant_table.c index 9436347779..7e25dda2f4 100644 --- a/xen/arch/ia64/grant_table.c +++ b/xen/arch/ia64/grant_table.c @@ -355,7 +355,7 @@ __gnttab_map_grant_ref( /* Bitwise-OR avoids short-circuiting which screws control flow. */ if ( unlikely(__get_user(dom, &uop->dom) | __get_user(ref, &uop->ref) | - __get_user(host_virt_addr, &uop->host_virt_addr) | + __get_user(host_virt_addr, &uop->host_addr) | __get_user(dev_hst_ro_flags, &uop->flags)) ) { DPRINTK("Fault while reading gnttab_map_grant_ref_t.\n"); @@ -500,7 +500,7 @@ __gnttab_unmap_grant_ref( ld = current->domain; /* Bitwise-OR avoids short-circuiting which screws control flow. */ - if ( unlikely(__get_user(virt, &uop->host_virt_addr) | + if ( unlikely(__get_user(virt, &uop->host_addr) | __get_user(frame, &uop->dev_bus_addr) | __get_user(handle, &uop->handle)) ) { diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 8cbb7cb2d1..4cf33a594f 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2268,6 +2268,197 @@ int do_mmu_update( return rc; } + +int update_grant_va_mapping_pte(unsigned long pte_addr, + l1_pgentry_t _nl1e, + struct domain *d, + struct vcpu *v) +{ + /* Caller must: + * . own d's BIGLOCK + * . already have 'get_page' correctly on the to-be-installed nl1e + * . be responsible for flushing the TLB + * . check PTE being installed isn't DISALLOWED + */ + + int rc = GNTST_okay; + void *va; + unsigned long gpfn, mfn; + struct pfn_info *page; + struct domain_mmap_cache mapcache, sh_mapcache; + u32 type_info; + l1_pgentry_t ol1e; + + /* Grant tables and shadow mode don't currently work together. */ + ASSERT( !shadow_mode_refcounts(d) ); + + /* There shouldn't be any strange bits set on the PTE. */ + ASSERT( (l1e_get_flags(_nl1e) & L1_DISALLOW_MASK) == 0); + + cleanup_writable_pagetable(d); + + domain_mmap_cache_init(&mapcache); + domain_mmap_cache_init(&sh_mapcache); + + gpfn = pte_addr >> PAGE_SHIFT; + mfn = __gpfn_to_mfn(d, gpfn); + + if ( unlikely(!get_page_from_pagenr(mfn, current->domain)) ) + { + MEM_LOG("Could not get page for normal update"); + rc = -EINVAL; + goto failed_norefs; + } + + va = map_domain_page_with_cache(mfn, &mapcache); + va = (void *)((unsigned long)va + + (unsigned long)(pte_addr & ~PAGE_MASK)); + page = &frame_table[mfn]; + + type_info = page->u.inuse.type_info; + if ( (type_info & PGT_type_mask) != PGT_l1_page_table) { + DPRINTK("Grant map attempted to update a non-L1 page\n"); + rc = -EINVAL; + goto failed; + } + + if ( likely(get_page_type(page, type_info & (PGT_type_mask|PGT_va_mask))) ) + { + + if ( unlikely(__copy_from_user(&ol1e, (l1_pgentry_t *)va, + sizeof(ol1e)) != 0) ) { + put_page_type(page); + rc = -EINVAL; + goto failed; + } + + if ( update_l1e(va, ol1e, _nl1e) ) + { + put_page_from_l1e(ol1e, d); + + if ( l1e_get_flags(ol1e) & _PAGE_PRESENT ) + rc = GNTST_flush_all; /* We don't know what vaddr to flush */ + else + rc = GNTST_okay; /* Caller need not invalidate TLB entry */ + + if ( unlikely(shadow_mode_enabled(d)) ) + shadow_l1_normal_pt_update(d, pte_addr, _nl1e, &sh_mapcache); + } + else + rc = -EINVAL; + + put_page_type(page); + } + + failed: + unmap_domain_page_with_cache(va, &mapcache); + put_page(page); + + failed_norefs: + domain_mmap_cache_destroy(&mapcache); + domain_mmap_cache_destroy(&sh_mapcache); + + return rc; +} + + + +int clear_grant_va_mapping_pte(unsigned long addr, unsigned long frame, + struct domain *d) +{ + /* Caller must: + * . own d's BIGLOCK + * . already have 'get_page' correctly on the to-be-installed nl1e + * . be responsible for flushing the TLB + * . check PTE being installed isn't DISALLOWED + */ + + int rc = GNTST_okay; + void *va; + unsigned long gpfn, mfn; + struct pfn_info *page; + struct domain_mmap_cache mapcache, sh_mapcache; + u32 type_info; + l1_pgentry_t ol1e; + + /* Grant tables and shadow mode don't work together. */ + ASSERT( !shadow_mode_refcounts(d) ); + + cleanup_writable_pagetable(d); + + domain_mmap_cache_init(&mapcache); + domain_mmap_cache_init(&sh_mapcache); + + gpfn = addr >> PAGE_SHIFT; + mfn = __gpfn_to_mfn(d, gpfn); + + if ( unlikely(!get_page_from_pagenr(mfn, current->domain)) ) + { + MEM_LOG("Could not get page for normal update"); + rc = -EINVAL; + goto failed_norefs; + } + + va = map_domain_page_with_cache(mfn, &mapcache); + va = (void *)((unsigned long)va + + (unsigned long)(addr & ~PAGE_MASK)); + page = &frame_table[mfn]; + + type_info = page->u.inuse.type_info; + if ( (type_info & PGT_type_mask) != PGT_l1_page_table) { + DPRINTK("Grant map attempted to update a non-L1 page\n"); + rc = -EINVAL; + goto failed; + } + + if ( likely(get_page_type(page, type_info & (PGT_type_mask|PGT_va_mask))) ) + { + if ( unlikely(__copy_from_user(&ol1e, (l1_pgentry_t *)va, + sizeof(ol1e)) != 0) ) + { + rc = -EINVAL; + put_page_type(page); + goto failed; + } + + /* + * Check that the virtual address supplied is actually mapped to frame. + */ + if ( unlikely((l1e_get_intpte(ol1e) >> PAGE_SHIFT) != frame )) + { + DPRINTK("PTE entry %lx for address %lx doesn't match frame %lx\n", + (unsigned long)l1e_get_intpte(ol1e), addr, frame); + rc = -EINVAL; + put_page_type(page); + goto failed; + } + + /* Delete pagetable entry. */ + if ( unlikely(__put_user(0, (unsigned long *)va))) + { + DPRINTK("Cannot delete PTE entry at %p.\n", va); + rc = -EINVAL; + } else { + if ( unlikely(shadow_mode_enabled(d)) ) + shadow_l1_normal_pt_update(d, addr, l1e_empty(), + &sh_mapcache); + } + put_page_type(page); + } + + failed: + unmap_domain_page_with_cache(va, &mapcache); + put_page(page); + + failed_norefs: + domain_mmap_cache_destroy(&mapcache); + domain_mmap_cache_destroy(&sh_mapcache); + + return rc; +} + + + /* This function assumes the caller is holding the domain's BIGLOCK * and is running in a shadow mode */ @@ -2283,7 +2474,7 @@ int update_grant_va_mapping(unsigned long va, * . check PTE being installed isn't DISALLOWED */ - int rc = 0; + int rc = GNTST_okay; l1_pgentry_t *pl1e; l1_pgentry_t ol1e; @@ -2305,9 +2496,9 @@ int update_grant_va_mapping(unsigned long va, { put_page_from_l1e(ol1e, d); if ( l1e_get_flags(ol1e) & _PAGE_PRESENT ) - rc = 0; /* Caller needs to invalidate TLB entry */ + rc = GNTST_flush_one; else - rc = 1; /* Caller need not invalidate TLB entry */ + rc = GNTST_okay; /* Caller need not invalidate TLB entry */ } else rc = -EINVAL; @@ -2324,6 +2515,40 @@ int update_grant_va_mapping(unsigned long va, return rc; } +int clear_grant_va_mapping(unsigned long addr, unsigned long frame) +{ + l1_pgentry_t *pl1e; + unsigned long _ol1e; + + pl1e = &linear_pg_table[l1_linear_offset(addr)]; + + if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) ) + { + DPRINTK("Could not find PTE entry for address %lx\n", addr); + return -EINVAL; + } + + /* + * Check that the virtual address supplied is actually mapped to + * frame. + */ + if ( unlikely((_ol1e >> PAGE_SHIFT) != frame )) + { + DPRINTK("PTE entry %lx for address %lx doesn't match frame %lx\n", + _ol1e, addr, frame); + return -EINVAL; + } + + /* Delete pagetable entry. */ + if ( unlikely(__put_user(0, (unsigned long *)pl1e))) + { + DPRINTK("Cannot delete PTE entry at %p.\n", (unsigned long *)pl1e); + return -EINVAL; + } + + return 0; +} + int do_update_va_mapping(unsigned long va, u64 val64, unsigned long flags) diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index fcf7f522b8..070a9127b2 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -336,26 +336,25 @@ void __init __start_xen(multiboot_info_t *mbi) /* Find a large enough RAM extent to stash the DOM0 modules. */ for ( i = 0; ; i++ ) { - if ( (e820.map[i].type == E820_RAM) && - (e820.map[i].size >= modules_length) && - ((e820.map[i].addr + e820.map[i].size) >= - (xenheap_phys_end + modules_length)) ) - { - /* Stash as near as possible to the beginning of the RAM extent. */ - initial_images_start = e820.map[i].addr; - if ( initial_images_start < xenheap_phys_end ) - initial_images_start = xenheap_phys_end; - initial_images_end = initial_images_start + modules_length; - break; - } - if ( i == e820.nr_map ) { printk("Not enough memory to stash the DOM0 kernel image.\n"); for ( ; ; ) ; } + + if ( (e820.map[i].type == E820_RAM) && + (e820.map[i].size >= modules_length) && + ((e820.map[i].addr + e820.map[i].size) >= + (xenheap_phys_end + modules_length)) ) + break; } + /* Stash as near as possible to the beginning of the RAM extent. */ + initial_images_start = e820.map[i].addr; + if ( initial_images_start < xenheap_phys_end ) + initial_images_start = xenheap_phys_end; + initial_images_end = initial_images_start + modules_length; + #if defined(CONFIG_X86_32) memmove((void *)initial_images_start, /* use low mapping */ (void *)mod[0].mod_start, /* use low mapping */ diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 03f9c8dd6a..b5bec9e229 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -6,6 +6,8 @@ * * Copyright (c) 2005 Christopher Clark * Copyright (c) 2004 K A Fraser + * Copyright (c) 2005 Andrew Warfield + * Modifications by Geoffrey Lefebvre are (c) Intel Research Cambridge * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -50,7 +52,7 @@ get_maptrack_handle( grant_table_t *t) { unsigned int h; - if ( unlikely((h = t->maptrack_head) == t->maptrack_limit) ) + if ( unlikely((h = t->maptrack_head) == (t->maptrack_limit - 1)) ) return -1; t->maptrack_head = t->maptrack[h].ref_and_flags >> MAPTRACK_REF_SHIFT; t->map_count++; @@ -73,7 +75,7 @@ __gnttab_activate_grant_ref( struct domain *granting_d, grant_ref_t ref, u16 dev_hst_ro_flags, - unsigned long host_virt_addr, + unsigned long addr, unsigned long *pframe ) /* OUT */ { domid_t sdom; @@ -95,7 +97,7 @@ __gnttab_activate_grant_ref( * Returns: * . -ve: error * . 1: ok - * . 0: ok and TLB invalidate of host_virt_addr needed. + * . 0: ok and TLB invalidate of host_addr needed. * * On success, *pframe contains mfn. */ @@ -121,6 +123,10 @@ __gnttab_activate_grant_ref( sflags = sha->flags; sdom = sha->domid; + /* This loop attempts to set the access (reading/writing) flags + * in the grant table entry. It tries a cmpxchg on the field + * up to five times, and then fails under the assumption that + * the guest is misbehaving. */ for ( ; ; ) { u32 scombo, prev_scombo, new_scombo; @@ -253,28 +259,37 @@ __gnttab_activate_grant_ref( /* * At this point: - * act->pin updated to reflect mapping. + * act->pin updated to reference count mappings. * sha->flags updated to indicate to granting domain mapping done. * frame contains the mfn. */ spin_unlock(&granting_d->grant_table->lock); - if ( (host_virt_addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) ) + + if ( (addr != 0) && (dev_hst_ro_flags & GNTMAP_host_map) ) { /* Write update into the pagetable. */ l1_pgentry_t pte; pte = l1e_from_pfn(frame, GRANT_PTE_FLAGS); + + if ( (dev_hst_ro_flags & GNTMAP_application_map) ) + l1e_add_flags(pte,_PAGE_USER); if ( !(dev_hst_ro_flags & GNTMAP_readonly) ) l1e_add_flags(pte,_PAGE_RW); - rc = update_grant_va_mapping( host_virt_addr, pte, - mapping_d, mapping_ed ); - /* - * IMPORTANT: (rc == 0) => must flush / invalidate entry in TLB. - * This is done in the outer gnttab_map_grant_ref. - */ + if (!(dev_hst_ro_flags & GNTMAP_contains_pte)) + { + rc = update_grant_va_mapping( addr, pte, + mapping_d, mapping_ed ); + } else { + rc = update_grant_va_mapping_pte( addr, pte, + mapping_d, mapping_ed ); + } + /* IMPORTANT: rc indicates the degree of TLB flush that is required. + * GNTST_flush_one (1) or GNTST_flush_all (2). This is done in the + * outer gnttab_map_grant_ref. */ if ( rc < 0 ) { /* Failure: undo and abort. */ @@ -317,6 +332,9 @@ __gnttab_activate_grant_ref( /* * Returns 0 if TLB flush / invalidate required by caller. * va will indicate the address to be invalidated. + * + * addr is _either_ a host virtual address, or the address of the pte to + * update, as indicated by the GNTMAP_contains_pte flag. */ static int __gnttab_map_grant_ref( @@ -326,10 +344,10 @@ __gnttab_map_grant_ref( domid_t dom; grant_ref_t ref; struct domain *ld, *rd; - struct vcpu *led; + struct vcpu *led; u16 dev_hst_ro_flags; int handle; - unsigned long frame = 0, host_virt_addr; + unsigned long frame = 0, addr; int rc; led = current; @@ -338,19 +356,20 @@ __gnttab_map_grant_ref( /* Bitwise-OR avoids short-circuiting which screws control flow. */ if ( unlikely(__get_user(dom, &uop->dom) | __get_user(ref, &uop->ref) | - __get_user(host_virt_addr, &uop->host_virt_addr) | + __get_user(addr, &uop->host_addr) | __get_user(dev_hst_ro_flags, &uop->flags)) ) { DPRINTK("Fault while reading gnttab_map_grant_ref_t.\n"); return -EFAULT; /* don't set status */ } - - if ( ((host_virt_addr != 0) || (dev_hst_ro_flags & GNTMAP_host_map)) && - unlikely(!__addr_ok(host_virt_addr))) + if ( (dev_hst_ro_flags & GNTMAP_host_map) && + ( (addr == 0) || + (!(dev_hst_ro_flags & GNTMAP_contains_pte) && + unlikely(!__addr_ok(addr))) ) ) { DPRINTK("Bad virtual address (%lx) or flags (%x).\n", - host_virt_addr, dev_hst_ro_flags); + addr, dev_hst_ro_flags); (void)__put_user(GNTST_bad_virt_addr, &uop->handle); return GNTST_bad_gntref; } @@ -386,12 +405,20 @@ __gnttab_map_grant_ref( grant_mapping_t *new_mt; grant_table_t *lgt = ld->grant_table; + if ( (lgt->maptrack_limit << 1) > MAPTRACK_MAX_ENTRIES ) + { + put_domain(rd); + DPRINTK("Maptrack table is at maximum size.\n"); + (void)__put_user(GNTST_no_device_space, &uop->handle); + return GNTST_no_device_space; + } + /* Grow the maptrack table. */ new_mt = alloc_xenheap_pages(lgt->maptrack_order + 1); if ( new_mt == NULL ) { put_domain(rd); - DPRINTK("No more map handles available\n"); + DPRINTK("No more map handles available.\n"); (void)__put_user(GNTST_no_device_space, &uop->handle); return GNTST_no_device_space; } @@ -405,7 +432,7 @@ __gnttab_map_grant_ref( lgt->maptrack_order += 1; lgt->maptrack_limit <<= 1; - printk("Doubled maptrack size\n"); + DPRINTK("Doubled maptrack size\n"); handle = get_maptrack_handle(ld->grant_table); } @@ -416,7 +443,7 @@ __gnttab_map_grant_ref( if ( 0 <= ( rc = __gnttab_activate_grant_ref( ld, led, rd, ref, dev_hst_ro_flags, - host_virt_addr, &frame))) + addr, &frame))) { /* * Only make the maptrack live _after_ writing the pte, in case we @@ -430,8 +457,9 @@ __gnttab_map_grant_ref( (void)__put_user(frame, &uop->dev_bus_addr); - if ( dev_hst_ro_flags & GNTMAP_host_map ) - *va = host_virt_addr; + if ( ( dev_hst_ro_flags & GNTMAP_host_map ) && + !( dev_hst_ro_flags & GNTMAP_contains_pte) ) + *va = addr; (void)__put_user(handle, &uop->handle); } @@ -449,12 +477,12 @@ static long gnttab_map_grant_ref( gnttab_map_grant_ref_t *uop, unsigned int count) { - int i, flush = 0; + int i, rc, flush = 0; unsigned long va = 0; for ( i = 0; i < count; i++ ) - if ( __gnttab_map_grant_ref(&uop[i], &va) == 0 ) - flush++; + if ( (rc =__gnttab_map_grant_ref(&uop[i], &va)) >= 0 ) + flush += rc; if ( flush == 1 ) flush_tlb_one_mask(current->domain->cpumask, va); @@ -479,12 +507,12 @@ __gnttab_unmap_grant_ref( grant_mapping_t *map; u16 flags; s16 rc = 1; - unsigned long frame, virt; + unsigned long frame, addr; ld = current->domain; /* Bitwise-OR avoids short-circuiting which screws control flow. */ - if ( unlikely(__get_user(virt, &uop->host_virt_addr) | + if ( unlikely(__get_user(addr, &uop->host_addr) | __get_user(frame, &uop->dev_bus_addr) | __get_user(handle, &uop->handle)) ) { @@ -554,41 +582,17 @@ __gnttab_unmap_grant_ref( /* Frame is now unmapped for device access. */ } - if ( (virt != 0) && + if ( (addr != 0) && (flags & GNTMAP_host_map) && ((act->pin & (GNTPIN_hstw_mask | GNTPIN_hstr_mask)) > 0)) { - l1_pgentry_t *pl1e; - unsigned long _ol1e; - - pl1e = &linear_pg_table[l1_linear_offset(virt)]; - - if ( unlikely(__get_user(_ol1e, (unsigned long *)pl1e) != 0) ) - { - DPRINTK("Could not find PTE entry for address %lx\n", virt); - rc = -EINVAL; - goto unmap_out; - } - - /* - * Check that the virtual address supplied is actually mapped to - * act->frame. - */ - if ( unlikely((_ol1e >> PAGE_SHIFT) != frame )) - { - DPRINTK("PTE entry %lx for address %lx doesn't match frame %lx\n", - _ol1e, virt, frame); - rc = -EINVAL; - goto unmap_out; - } - - /* Delete pagetable entry. */ - if ( unlikely(__put_user(0, (unsigned long *)pl1e))) + if (flags & GNTMAP_contains_pte) { - DPRINTK("Cannot delete PTE entry at %p for virtual address %lx\n", - pl1e, virt); - rc = -EINVAL; - goto unmap_out; + if ( (rc = clear_grant_va_mapping_pte(addr, frame, ld)) < 0 ) + goto unmap_out; + } else { + if ( (rc = clear_grant_va_mapping(addr, frame)) < 0 ) + goto unmap_out; } map->ref_and_flags &= ~GNTMAP_host_map; @@ -606,7 +610,8 @@ __gnttab_unmap_grant_ref( } rc = 0; - *va = virt; + if ( !( flags & GNTMAP_contains_pte) ) + *va = addr; } if ( (map->ref_and_flags & (GNTMAP_device_map|GNTMAP_host_map)) == 0) @@ -630,6 +635,7 @@ __gnttab_unmap_grant_ref( if ( act->pin == 0 ) { + act->frame = 0xdeadbeef; clear_bit(_GTF_reading, &sha->flags); put_page(&frame_table[frame]); } @@ -769,7 +775,8 @@ gnttab_dump_table(gnttab_dump_table_t *uop) { DPRINTK("Grant: dom (%hu) SHARED (%d) flags:(%hx) " "dom:(%hu) frame:(%lx)\n", - op.dom, i, sha_copy.flags, sha_copy.domid, sha_copy.frame); + op.dom, i, sha_copy.flags, sha_copy.domid, + (unsigned long) sha_copy.frame); } } @@ -823,7 +830,7 @@ gnttab_donate(gnttab_donate_t *uop, unsigned int count) gnttab_donate_t *gop = &uop[i]; #if GRANT_DEBUG printk("gnttab_donate: i=%d mfn=%08x domid=%d gref=%08x\n", - i, gop->mfn, gop->domid, gop->handle); + i, (unsigned int)gop->mfn, gop->domid, gop->handle); #endif page = &frame_table[gop->mfn]; @@ -1027,7 +1034,7 @@ gnttab_check_unmap( if ( ld->domain_id != 0 ) { DPRINTK("Foreign unref rd(%d) ld(%d) frm(%x) flgs(%x).\n", - rd->domain_id, ld->domain_id, frame, readonly); + rd->domain_id, ld->domain_id, (unsigned int)frame, readonly); } #endif diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 505481253e..b0389df3dd 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -381,4 +381,13 @@ int update_grant_va_mapping(unsigned long va, l1_pgentry_t _nl1e, struct domain *d, struct vcpu *v); +int update_grant_va_mapping_pte(unsigned long pte_addr, + l1_pgentry_t _nl1e, + struct domain *d, + struct vcpu *v); + +int clear_grant_va_mapping(unsigned long addr, unsigned long frame); +int clear_grant_va_mapping_pte(unsigned long addr, unsigned long frame, + struct domain *d); + #endif /* __ASM_X86_MM_H__ */ diff --git a/xen/include/public/grant_table.h b/xen/include/public/grant_table.h index 4522d52571..b70bb65856 100644 --- a/xen/include/public/grant_table.h +++ b/xen/include/public/grant_table.h @@ -142,7 +142,10 @@ typedef u16 grant_ref_t; * 1. If GNTPIN_map_for_dev is specified then <dev_bus_addr> is the address * via which I/O devices may access the granted frame. * 2. If GNTPIN_map_for_host is specified then a mapping will be added at - * virtual address <host_virt_addr> in the current address space. + * either a host virtual address in the current address space, or at + * a PTE at the specified machine address. The type of mapping to + * perform is selected through the GNTMAP_contains_pte flag, and the + * address is specified in <host_addr>. * 3. Mappings should only be destroyed via GNTTABOP_unmap_grant_ref. If a * host mapping is destroyed by other means then it is *NOT* guaranteed * to be accounted to the correct grant reference! @@ -150,7 +153,7 @@ typedef u16 grant_ref_t; #define GNTTABOP_map_grant_ref 0 typedef struct gnttab_map_grant_ref { /* IN parameters. */ - memory_t host_virt_addr; + memory_t host_addr; domid_t dom; grant_ref_t ref; u16 flags; /* GNTMAP_* */ @@ -161,7 +164,7 @@ typedef struct gnttab_map_grant_ref { /* * GNTTABOP_unmap_grant_ref: Destroy one or more grant-reference mappings - * tracked by <handle>. If <host_virt_addr> or <dev_bus_addr> is zero, that + * tracked by <handle>. If <host_addr> or <dev_bus_addr> is zero, that * field is ignored. If non-zero, they must refer to a device/host mapping * that is tracked by <handle> * NOTES: @@ -173,7 +176,7 @@ typedef struct gnttab_map_grant_ref { #define GNTTABOP_unmap_grant_ref 1 typedef struct gnttab_unmap_grant_ref { /* IN parameters. */ - memory_t host_virt_addr; + memory_t host_addr; memory_t dev_bus_addr; u16 handle; /* OUT parameters. */ @@ -247,10 +250,20 @@ typedef struct { #define _GNTMAP_application_map (3) #define GNTMAP_application_map (1<<_GNTMAP_application_map) + /* + * GNTMAP_contains_pte subflag: + * 0 => This map request contains a host virtual address. + * 1 => This map request contains the machine addess of the PTE to update. + */ +#define _GNTMAP_contains_pte (4) +#define GNTMAP_contains_pte (1<<_GNTMAP_contains_pte) + /* * Values for error status returns. All errors are -ve. */ -#define GNTST_okay (0) +#define GNTST_flush_all (2) /* Success, need to flush entire TLB. */ +#define GNTST_flush_one (1) /* Success, need to flush a vaddr. */ +#define GNTST_okay (0) /* Normal return. */ #define GNTST_general_error (-1) /* General undefined error. */ #define GNTST_bad_domain (-2) /* Unrecognsed domain id. */ #define GNTST_bad_gntref (-3) /* Unrecognised or inappropriate gntref. */ diff --git a/xen/include/xen/grant_table.h b/xen/include/xen/grant_table.h index c273eacada..1250c5abaf 100644 --- a/xen/include/xen/grant_table.h +++ b/xen/include/xen/grant_table.h @@ -61,11 +61,12 @@ typedef struct { * table of these, indexes into which are returned as a 'mapping handle'. */ typedef struct { - u16 ref_and_flags; /* 0-2: GNTMAP_* ; 3-15: grant ref */ + u16 ref_and_flags; /* 0-4: GNTMAP_* ; 5-15: grant ref */ domid_t domid; /* granting domain */ } grant_mapping_t; -#define MAPTRACK_GNTMAP_MASK 7 -#define MAPTRACK_REF_SHIFT 3 +#define MAPTRACK_GNTMAP_MASK 0x1f +#define MAPTRACK_REF_SHIFT 5 +#define MAPTRACK_MAX_ENTRIES ( 1 << (16 - MAPTRACK_REF_SHIFT) ) /* Per-domain grant information. */ typedef struct { |