From f2f33db0f49599547622230bbcea89779af8ec15 Mon Sep 17 00:00:00 2001 From: "iap10@freefall.cl.cam.ac.uk" Date: Wed, 7 Sep 2005 23:10:49 +0000 Subject: [PATCH 01/13] Replace direct_remap_area_pages with direct_remap_pfn_range to help fix PAE domain building. Signed-off-by: ian@xensource.com --- .../arch/xen/i386/mm/ioremap.c | 19 +++++++++++-------- .../drivers/xen/netback/interface.c | 8 ++++---- .../drivers/xen/privcmd/privcmd.c | 4 ++-- .../drivers/xen/usbback/interface.c | 4 ++-- .../include/asm-xen/asm-i386/pgtable.h | 8 ++++---- .../include/asm-xen/asm-x86_64/pgtable.h | 14 ++++++-------- 6 files changed, 29 insertions(+), 28 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c index 8e14408d54..8016210ece 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/ioremap.c @@ -22,13 +22,14 @@ #define ISA_START_ADDRESS 0x0 #define ISA_END_ADDRESS 0x100000 +#if 0 /* not PAE safe */ /* These hacky macros avoid phys->machine translations. */ #define __direct_pte(x) ((pte_t) { (x) } ) #define __direct_mk_pte(page_nr,pgprot) \ __direct_pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot)) #define direct_mk_pte_phys(physpage, pgprot) \ __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot) - +#endif static int direct_remap_area_pte_fn(pte_t *pte, struct page *pte_page, @@ -37,16 +38,16 @@ static int direct_remap_area_pte_fn(pte_t *pte, { mmu_update_t **v = (mmu_update_t **)data; - (*v)->ptr = ((maddr_t)pfn_to_mfn(page_to_pfn(pte_page)) << + (*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pte_page)) << PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK); (*v)++; return 0; } -int direct_remap_area_pages(struct mm_struct *mm, +int direct_remap_pfn_range(struct mm_struct *mm, unsigned long address, - unsigned long machine_addr, + unsigned long mfn, unsigned long size, pgprot_t prot, domid_t domid) @@ -77,9 +78,9 @@ int direct_remap_area_pages(struct mm_struct *mm, * Fill in the machine address: PTE ptr is done later by * __direct_remap_area_pages(). */ - v->val = pte_val_ma(pfn_pte_ma(machine_addr >> PAGE_SHIFT, prot)); + v->val = pte_val_ma(pfn_pte_ma(mfn, prot)); - machine_addr += PAGE_SIZE; + mfn++; address += PAGE_SIZE; v++; } @@ -97,8 +98,10 @@ int direct_remap_area_pages(struct mm_struct *mm, return 0; } -EXPORT_SYMBOL(direct_remap_area_pages); +EXPORT_SYMBOL(direct_remap_pfn_range); + +/* FIXME: This is horribly broken on PAE */ static int lookup_pte_fn( pte_t *pte, struct page *pte_page, unsigned long addr, void *data) { @@ -218,7 +221,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l #ifdef __x86_64__ flags |= _PAGE_USER; #endif - if (direct_remap_area_pages(&init_mm, (unsigned long) addr, phys_addr, + if (direct_remap_pfn_range(&init_mm, (unsigned long) addr, phys_addr>>PAGE_SHIFT, size, __pgprot(flags), domid)) { vunmap((void __force *) addr); return NULL; diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c index c1694fe7bb..8b42041e62 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c @@ -154,12 +154,12 @@ static int map_frontend_pages(netif_t *netif, unsigned long localaddr, pgprot_t prot = __pgprot(_KERNPG_TABLE); int err; - err = direct_remap_area_pages(&init_mm, localaddr, - tx_ring_ref<domid); - err |= direct_remap_area_pages(&init_mm, localaddr + PAGE_SIZE, - rx_ring_ref<domid); if (err) diff --git a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c index ed068a06c6..a2965a0e70 100644 --- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c +++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c @@ -116,9 +116,9 @@ static int privcmd_ioctl(struct inode *inode, struct file *file, if ( (msg[j].va + (msg[j].npages< vma->vm_end ) return -EINVAL; - if ( (rc = direct_remap_area_pages(vma->vm_mm, + if ( (rc = direct_remap_pfn_range(vma->vm_mm, msg[j].va&PAGE_MASK, - msg[j].mfn<vm_page_prot, mmapcmd.dom)) < 0 ) diff --git a/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c b/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c index 27365b3fa6..ab44ed3040 100644 --- a/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c @@ -161,8 +161,8 @@ void usbif_connect(usbif_be_connect_t *connect) } prot = __pgprot(_KERNPG_TABLE); - error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr), - shmem_frame<addr), + shmem_frame, PAGE_SIZE, prot, domid); if ( error != 0 ) { diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h index 6e33a59886..4779997177 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pgtable.h @@ -460,9 +460,9 @@ void make_pages_writable(void *va, unsigned int nr); #define kern_addr_valid(addr) (1) #endif /* !CONFIG_DISCONTIGMEM */ -int direct_remap_area_pages(struct mm_struct *mm, +int direct_remap_pfn_range(struct mm_struct *mm, unsigned long address, - unsigned long machine_addr, + unsigned long mfn, unsigned long size, pgprot_t prot, domid_t domid); @@ -474,10 +474,10 @@ int touch_pte_range(struct mm_struct *mm, unsigned long size); #define io_remap_page_range(vma,from,phys,size,prot) \ -direct_remap_area_pages(vma->vm_mm,from,phys,size,prot,DOMID_IO) +direct_remap_pfn_range(vma->vm_mm,from,phys>>PAGE_SHIFT,size,prot,DOMID_IO) #define io_remap_pfn_range(vma,from,pfn,size,prot) \ -direct_remap_area_pages(vma->vm_mm,from,pfn<vm_mm,from,pfn,size,prot,DOMID_IO) #define MK_IOSPACE_PFN(space, pfn) (pfn) #define GET_IOSPACE(pfn) 0 diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h index e8f986c452..86f1b4f7fa 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pgtable.h @@ -526,28 +526,26 @@ extern int kern_addr_valid(unsigned long addr); #define DOMID_LOCAL (0xFFFFU) -int direct_remap_area_pages(struct mm_struct *mm, +int direct_remap_pfn_range(struct mm_struct *mm, unsigned long address, - unsigned long machine_addr, + unsigned long mfn, unsigned long size, pgprot_t prot, domid_t domid); -int __direct_remap_area_pages(struct mm_struct *mm, - unsigned long address, - unsigned long size, - mmu_update_t *v); + int create_lookup_pte_addr(struct mm_struct *mm, unsigned long address, unsigned long *ptep); + int touch_pte_range(struct mm_struct *mm, unsigned long address, unsigned long size); #define io_remap_page_range(vma, vaddr, paddr, size, prot) \ - direct_remap_area_pages((vma)->vm_mm,vaddr,paddr,size,prot,DOMID_IO) + direct_remap_pfn_range((vma)->vm_mm,vaddr,paddr>>PAGE_SHIFT,size,prot,DOMID_IO) #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ - direct_remap_area_pages((vma)->vm_mm,vaddr,(pfn)<vm_mm,vaddr,pfn,size,prot,DOMID_IO) #define MK_IOSPACE_PFN(space, pfn) (pfn) #define GET_IOSPACE(pfn) 0 From 558b5c7a896045a1378e6d1569a008bb85e8bf44 Mon Sep 17 00:00:00 2001 From: "iap10@freefall.cl.cam.ac.uk" Date: Wed, 7 Sep 2005 23:11:44 +0000 Subject: [PATCH 02/13] More tools PAE fixes to avoid loosing high-order pte bits. Signed-off-by: ian@xensource.com --- tools/libxc/xc_linux_build.c | 20 ++++++++++++++------ tools/libxc/xc_private.c | 6 +++--- tools/libxc/xenctrl.h | 2 +- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 498cb75542..4525996f2a 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -57,7 +57,7 @@ static int probeimageformat(char *image, } #define alloc_pt(ltab, vltab) \ - ltab = page_array[ppt_alloc++] << PAGE_SHIFT; \ + ltab = (unsigned long long)(page_array[ppt_alloc++]) << PAGE_SHIFT; \ if (vltab != NULL) { \ munmap(vltab, PAGE_SIZE); \ } \ @@ -128,9 +128,9 @@ static int setup_pg_tables_pae(int xc_handle, u32 dom, l1_pgentry_64_t *vl1tab=NULL, *vl1e=NULL; l2_pgentry_64_t *vl2tab=NULL, *vl2e=NULL; l3_pgentry_64_t *vl3tab=NULL, *vl3e=NULL; - unsigned long l1tab = 0; - unsigned long l2tab = 0; - unsigned long l3tab = 0; + unsigned long long l1tab = 0; + unsigned long long l2tab = 0; + unsigned long long l3tab = 0; unsigned long ppt_alloc; unsigned long count; @@ -139,7 +139,13 @@ static int setup_pg_tables_pae(int xc_handle, u32 dom, alloc_pt(l3tab, vl3tab); vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)]; ctxt->ctrlreg[3] = l3tab; - + + if(l3tab>0xfffff000) + { + fprintf(stderr,"L3TAB = %llx above 4GB!\n",l3tab); + goto error_out; + } + for ( count = 0; count < ((v_end-dsi_v_start)>>PAGE_SHIFT); count++) { if ( !((unsigned long)vl1e & (PAGE_SIZE-1)) ) @@ -525,12 +531,14 @@ static int setup_guest(int xc_handle, physmap = physmap_e = xc_map_foreign_range( xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, page_array[physmap_pfn++]); + for ( count = 0; count < nr_pages; count++ ) { if ( xc_add_mmu_update(xc_handle, mmu, - (page_array[count] << PAGE_SHIFT) | + ((unsigned long long)page_array[count] << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, count) ) { + fprintf(stderr,"m2p update failure p=%lx m=%lx\n",count,page_array[count] ); munmap(physmap, PAGE_SIZE); goto error_out; } diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 4cbfa2f1f2..58392cc07e 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -116,7 +116,7 @@ int xc_mmuext_op( if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 ) { - fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to" + fprintf(stderr, "Dom_mmuext operation failed (rc=%ld errno=%d)-- need to" " rebuild the user-space tool set?\n",ret,errno); } @@ -172,7 +172,7 @@ xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom) } int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu, - unsigned long ptr, unsigned long val) + unsigned long long ptr, unsigned long long val) { mmu->updates[mmu->idx].ptr = ptr; mmu->updates[mmu->idx].val = val; @@ -229,7 +229,7 @@ int xc_memory_op(int xc_handle, if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 ) { - fprintf(stderr, "Dom_mem operation failed (rc=%ld errno=%d)-- need to" + fprintf(stderr, "hypercall failed (rc=%ld errno=%d)-- need to" " rebuild the user-space tool set?\n",ret,errno); } diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 16a6339a5e..0c89052111 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -521,7 +521,7 @@ struct xc_mmu { typedef struct xc_mmu xc_mmu_t; xc_mmu_t *xc_init_mmu_updates(int xc_handle, domid_t dom); int xc_add_mmu_update(int xc_handle, xc_mmu_t *mmu, - unsigned long ptr, unsigned long val); + unsigned long long ptr, unsigned long long val); int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu); #endif From 73167306c72d2fde1c39b1cb35314aa327cfaff9 Mon Sep 17 00:00:00 2001 From: "iap10@freefall.cl.cam.ac.uk" Date: Thu, 8 Sep 2005 01:00:04 +0000 Subject: [PATCH 03/13] Yet more PAE fixes, this time in the paravirt drivers. Signed-off-by: ian@xensource.com --- linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 8 ++++---- linux-2.6-xen-sparse/drivers/xen/netback/netback.c | 2 +- linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index a507f66d93..8226222db4 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -182,7 +182,7 @@ int blkif_ioctl(struct inode *inode, struct file *filep, static int blkif_queue_request(struct request *req) { struct blkfront_info *info = req->rq_disk->private_data; - unsigned long buffer_ma; + unsigned long buffer_mfn; blkif_request_t *ring_req; struct bio *bio; struct bio_vec *bvec; @@ -221,7 +221,7 @@ static int blkif_queue_request(struct request *req) bio_for_each_segment (bvec, bio, idx) { BUG_ON(ring_req->nr_segments == BLKIF_MAX_SEGMENTS_PER_REQUEST); - buffer_ma = page_to_phys(bvec->bv_page); + buffer_mfn = page_to_phys(bvec->bv_page) >> PAGE_SHIFT; fsect = bvec->bv_offset >> 9; lsect = fsect + (bvec->bv_len >> 9) - 1; /* install a grant reference. */ @@ -231,11 +231,11 @@ static int blkif_queue_request(struct request *req) gnttab_grant_foreign_access_ref( ref, info->backend_id, - buffer_ma >> PAGE_SHIFT, + buffer_mfn, rq_data_dir(req) ); info->shadow[id].frame[ring_req->nr_segments] = - buffer_ma >> PAGE_SHIFT; + buffer_mfn; ring_req->frame_and_sects[ring_req->nr_segments] = blkif_fas_from_gref(ref, fsect, lsect); 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 32ceb5f0b9..40eac7b491 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c @@ -297,7 +297,7 @@ static void net_rx_action(unsigned long unused) mmuext->mfn = old_mfn; mmuext++; #endif - mmu->ptr = (new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; + mmu->ptr = ((unsigned long long)new_mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; mmu->val = __pa(vdata) >> PAGE_SHIFT; mmu++; diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index 45755083de..e31434ac12 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -618,7 +618,7 @@ static int netif_poll(struct net_device *dev, int *pbudget) /* Remap the page. */ #ifdef CONFIG_XEN_NETDEV_GRANT - mmu->ptr = mfn << PAGE_SHIFT | MMU_MACHPHYS_UPDATE; + mmu->ptr = ((unsigned long long)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE; #else mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE; #endif From 8b1b30d3cbbfdae647d57aeaac2b9b999cd6f968 Mon Sep 17 00:00:00 2001 From: "iap10@freefall.cl.cam.ac.uk" Date: Thu, 8 Sep 2005 01:07:15 +0000 Subject: [PATCH 04/13] Give each domain some memory below 4GB. This solves the "PGD's must be below 4GB" for the initial page tables. I'm not sure we'll stick with this approach, but this is good enough for the time being. PAE should be a *lot* more robust on systems that actually have more than 4GB thanks to all the various patches that went in today. I find it astounding that it ever appeared to work at all! Signed-off-by: ian@xensource.com --- tools/libxc/xc_domain.c | 9 +++++++-- tools/libxc/xc_linux_build.c | 8 ++++++++ tools/libxc/xc_linux_restore.c | 4 ++-- tools/libxc/xenctrl.h | 4 +++- tools/python/xen/lowlevel/xc/xc.c | 10 ++++++---- tools/python/xen/xend/image.py | 6 +++++- xen/common/memory.c | 2 +- 7 files changed, 32 insertions(+), 11 deletions(-) diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 4b6771fd04..2c3a3a998c 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -262,13 +262,16 @@ int xc_domain_setmaxmem(int xc_handle, int xc_domain_memory_increase_reservation(int xc_handle, u32 domid, - unsigned int mem_kb) + unsigned long mem_kb, + unsigned int extent_order, + unsigned int address_bits) { int err; unsigned int npages = mem_kb / (PAGE_SIZE/1024); struct xen_memory_reservation reservation = { .nr_extents = npages, - .extent_order = 0, + .extent_order = extent_order, + .address_bits = address_bits, .domid = domid }; @@ -277,6 +280,8 @@ int xc_domain_memory_increase_reservation(int xc_handle, return 0; if (err > 0) { + fprintf(stderr,"Failed alocation for dom %d : %d pages order %d addr_bits %d\n", + domid, npages, extent_order, address_bits); errno = ENOMEM; err = -1; } diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 4525996f2a..89a71a4695 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -270,6 +270,11 @@ static int setup_pg_tables_64(int xc_handle, u32 dom, } #endif +static int compare (const void * a, const void * b) +{ + return ( *(long*)a - *(long*)b ); +} + #ifdef __ia64__ #include /* for FPSR_DEFAULT */ static int setup_guest(int xc_handle, @@ -483,6 +488,9 @@ static int setup_guest(int xc_handle, goto error_out; } + qsort( page_array, nr_pages, sizeof(*page_array), compare ); + + (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array, &dsi); diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index b60c629e91..d953ad2a48 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -149,9 +149,9 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns, } err = xc_domain_memory_increase_reservation(xc_handle, dom, - nr_pfns * PAGE_SIZE / 1024); + nr_pfns * PAGE_SIZE / 1024, 0, 0); //FIX ME if (err != 0) { - ERR("Failed to increate reservation by %lx\n", + ERR("Failed to increase reservation by %lx\n", nr_pfns * PAGE_SIZE / 1024); errno = ENOMEM; goto out; diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 0c89052111..006e647825 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -387,7 +387,9 @@ int xc_domain_setmaxmem(int xc_handle, int xc_domain_memory_increase_reservation(int xc_handle, u32 domid, - unsigned int mem_kb); + unsigned long mem_kb, + unsigned int extent_order, + unsigned int address_bits); typedef dom0_perfc_desc_t xc_perfc_desc_t; /* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */ diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index e173f943cc..e4a96be580 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -841,14 +841,16 @@ static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self, u32 dom; unsigned long mem_kb; + unsigned int extent_order = 0 , address_bits = 0; - static char *kwd_list[] = { "dom", "mem_kb", NULL }; + static char *kwd_list[] = { "dom", "mem_kb", "extent_order", "address_bits", NULL }; - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list, - &dom, &mem_kb) ) + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii|ii", kwd_list, + &dom, &mem_kb, &extent_order, &address_bits) ) return NULL; - if ( xc_domain_memory_increase_reservation(xc->xc_handle, dom, mem_kb) ) + if ( xc_domain_memory_increase_reservation(xc->xc_handle, dom, + mem_kb, extent_order, address_bits) ) return PyErr_SetFromErrno(xc_error); Py_INCREF(zero); diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 721dd3dab3..4403e8d886 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -159,7 +159,11 @@ class ImageHandler: xc.domain_setmaxmem(dom, mem_kb) try: - xc.domain_memory_increase_reservation(dom, mem_kb) + # Give the domain some memory below 4GB + lmem_kb = 4096 + xc.domain_memory_increase_reservation(dom, min(lmem_kb,mem_kb), 0, 32) + if mem_kb > lmem_kb: + xc.domain_memory_increase_reservation(dom, mem_kb-lmem_kb, 0, 0) except: xc.domain_destroy(dom) raise diff --git a/xen/common/memory.c b/xen/common/memory.c index ca394edb81..5185852b3f 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -52,7 +52,7 @@ increase_reservation( if ( unlikely((page = alloc_domheap_pages( d, extent_order, flags)) == NULL) ) { - DPRINTK("Could not allocate a frame\n"); + DPRINTK("Could not allocate a frame id=%d %d flags=%x\n", d->domain_id, extent_order, flags); return i; } From d86b993b36c9eed694dfd3e16ab4eb694d58ee51 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 8 Sep 2005 15:22:01 +0000 Subject: [PATCH 05/13] Cleanups, and fix allocating DMA memory via HYPERVISOR_memory_op(). Signed-off-by: Keir Fraser --- xen/common/memory.c | 15 ++++++++------- xen/common/page_alloc.c | 41 +++++++++++++++++++---------------------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/xen/common/memory.c b/xen/common/memory.c index 5185852b3f..a744272539 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -31,8 +31,8 @@ increase_reservation( struct pfn_info *page; unsigned long i; - if ( (extent_list != NULL) - && !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) ) + if ( (extent_list != NULL) && + !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) ) return 0; if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) ) @@ -52,13 +52,14 @@ increase_reservation( if ( unlikely((page = alloc_domheap_pages( d, extent_order, flags)) == NULL) ) { - DPRINTK("Could not allocate a frame id=%d %d flags=%x\n", d->domain_id, extent_order, flags); + DPRINTK("Could not allocate order=%d extent: id=%d flags=%x\n", + extent_order, d->domain_id, flags); return i; } /* Inform the domain of the new page's machine address. */ - if ( (extent_list != NULL) - && (__put_user(page_to_pfn(page), &extent_list[i]) != 0) ) + if ( (extent_list != NULL) && + (__put_user(page_to_pfn(page), &extent_list[i]) != 0) ) return i; } @@ -152,8 +153,8 @@ long do_memory_op(int cmd, void *arg) reservation.extent_start += start_extent; reservation.nr_extents -= start_extent; - if ( unlikely(reservation.address_bits != 0) - && (reservation.address_bits > (get_order(max_page)+PAGE_SHIFT)) ) + if ( (reservation.address_bits != 0) && + (reservation.address_bits < (get_order(max_page) + PAGE_SHIFT)) ) { if ( reservation.address_bits < 31 ) return -ENOMEM; diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index 9e1059aadd..d4ae62ee2e 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -216,7 +216,7 @@ unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align) #define NR_ZONES 3 -#define MAX_DMADOM_PFN 0x7FFFF /* 31 addressable bits */ +#define MAX_DMADOM_PFN 0x7FFFFUL /* 31 addressable bits */ #define pfn_dom_zone_type(_pfn) \ (((_pfn) <= MAX_DMADOM_PFN) ? MEMZONE_DMADOM : MEMZONE_DOM) @@ -485,43 +485,40 @@ void free_xenheap_pages(void *v, unsigned int order) void init_domheap_pages(physaddr_t ps, physaddr_t pe) { + unsigned long s_tot, e_tot, s_dma, e_dma, s_nrm, e_nrm; + ASSERT(!in_irq()); - ps = round_pgup(ps) >> PAGE_SHIFT; - pe = round_pgdown(pe) >> PAGE_SHIFT; - if ( pe <= ps ) - return; + s_tot = round_pgup(ps) >> PAGE_SHIFT; + e_tot = round_pgdown(pe) >> PAGE_SHIFT; - if ( (ps < MAX_DMADOM_PFN) && (pe > MAX_DMADOM_PFN) ) - { - init_heap_pages( - MEMZONE_DMADOM, pfn_to_page(ps), MAX_DMADOM_PFN - ps); - init_heap_pages( - MEMZONE_DOM, pfn_to_page(MAX_DMADOM_PFN), pe - MAX_DMADOM_PFN); - } - else - { - init_heap_pages(pfn_dom_zone_type(ps), pfn_to_page(ps), pe - ps); - } + s_dma = min(s_tot, MAX_DMADOM_PFN + 1); + e_dma = min(e_tot, MAX_DMADOM_PFN + 1); + if ( s_dma < e_dma ) + init_heap_pages(MEMZONE_DMADOM, pfn_to_page(s_dma), e_dma - s_dma); + + s_nrm = max(s_tot, MAX_DMADOM_PFN + 1); + e_nrm = max(e_tot, MAX_DMADOM_PFN + 1); + if ( s_nrm < e_nrm ) + init_heap_pages(MEMZONE_DOM, pfn_to_page(s_nrm), e_nrm - s_nrm); } struct pfn_info *alloc_domheap_pages( struct domain *d, unsigned int order, unsigned int flags) { - struct pfn_info *pg; + struct pfn_info *pg = NULL; cpumask_t mask; int i; ASSERT(!in_irq()); - pg = NULL; - if (! (flags & ALLOC_DOM_DMA)) + if ( !(flags & ALLOC_DOM_DMA) ) pg = alloc_heap_pages(MEMZONE_DOM, order); - if (pg == NULL) { - if ( unlikely((pg = alloc_heap_pages(MEMZONE_DMADOM, order)) == NULL) ) + + if ( pg == NULL ) + if ( (pg = alloc_heap_pages(MEMZONE_DMADOM, order)) == NULL ) return NULL; - } mask = pg->u.free.cpumask; tlbflush_filter(mask, pg->tlbflush_timestamp); From 3bc2a39e2290e1587f48c71e790f84dbae5c1f4f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 8 Sep 2005 17:25:52 +0000 Subject: [PATCH 06/13] Rename get_order() to get_order_from_bytes() and add new function get_order_from_pages(). Fix HYPERVISOR_memory_op(), properly this time. Signed-off-by: Keir Fraser --- xen/arch/x86/domain.c | 12 ++++++++---- xen/arch/x86/domain_build.c | 11 ++++------- xen/arch/x86/vmx_vmcs.c | 8 ++++---- xen/arch/x86/x86_32/mm.c | 3 ++- xen/common/memory.c | 3 ++- xen/common/trace.c | 2 +- xen/common/xmalloc.c | 4 ++-- xen/drivers/char/console.c | 2 +- xen/drivers/char/serial.c | 5 +++-- xen/include/asm-x86/page.h | 11 ++++++++++- 10 files changed, 37 insertions(+), 24 deletions(-) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 7a15059416..0ae19d1ea3 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -381,11 +381,13 @@ static int vmx_final_setup_guest( out: free_vmcs(vmcs); if(v->arch.arch_vmx.io_bitmap_a != 0) { - free_xenheap_pages(v->arch.arch_vmx.io_bitmap_a, get_order(0x1000)); + free_xenheap_pages( + v->arch.arch_vmx.io_bitmap_a, get_order_from_bytes(0x1000)); v->arch.arch_vmx.io_bitmap_a = 0; } if(v->arch.arch_vmx.io_bitmap_b != 0) { - free_xenheap_pages(v->arch.arch_vmx.io_bitmap_b, get_order(0x1000)); + free_xenheap_pages( + v->arch.arch_vmx.io_bitmap_b, get_order_from_bytes(0x1000)); v->arch.arch_vmx.io_bitmap_b = 0; } v->arch.arch_vmx.vmcs = 0; @@ -972,11 +974,13 @@ static void vmx_relinquish_resources(struct vcpu *v) BUG_ON(v->arch.arch_vmx.vmcs == NULL); free_vmcs(v->arch.arch_vmx.vmcs); if(v->arch.arch_vmx.io_bitmap_a != 0) { - free_xenheap_pages(v->arch.arch_vmx.io_bitmap_a, get_order(0x1000)); + free_xenheap_pages( + v->arch.arch_vmx.io_bitmap_a, get_order_from_bytes(0x1000)); v->arch.arch_vmx.io_bitmap_a = 0; } if(v->arch.arch_vmx.io_bitmap_b != 0) { - free_xenheap_pages(v->arch.arch_vmx.io_bitmap_b, get_order(0x1000)); + free_xenheap_pages( + v->arch.arch_vmx.io_bitmap_b, get_order_from_bytes(0x1000)); v->arch.arch_vmx.io_bitmap_b = 0; } v->arch.arch_vmx.vmcs = 0; diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 98a7ec0902..0d1795150b 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -75,15 +75,12 @@ static struct pfn_info *alloc_chunk(struct domain *d, unsigned long max_pages) struct pfn_info *page; unsigned int order; /* - * Allocate up to 2MB at a time: - * 1. This prevents overflow of get_order() when allocating more than - * 4GB to domain 0 on a PAE machine. - * 2. It prevents allocating very large chunks from DMA pools before - * the >4GB pool is fully depleted. + * Allocate up to 2MB at a time: It prevents allocating very large chunks + * from DMA pools before the >4GB pool is fully depleted. */ if ( max_pages > (2UL << (20 - PAGE_SHIFT)) ) max_pages = 2UL << (20 - PAGE_SHIFT); - order = get_order(max_pages << PAGE_SHIFT); + order = get_order_from_pages(max_pages); if ( (max_pages & (max_pages-1)) != 0 ) order--; while ( (page = alloc_domheap_pages(d, order, 0)) == NULL ) @@ -252,7 +249,7 @@ int construct_dom0(struct domain *d, #endif } - order = get_order(v_end - dsi.v_start); + order = get_order_from_bytes(v_end - dsi.v_start); if ( (1UL << order) > nr_pages ) panic("Domain 0 allocation is too small for kernel image.\n"); diff --git a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/vmx_vmcs.c index 8a2402fd9a..a870044b15 100644 --- a/xen/arch/x86/vmx_vmcs.c +++ b/xen/arch/x86/vmx_vmcs.c @@ -44,7 +44,7 @@ struct vmcs_struct *alloc_vmcs(void) rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high); vmcs_size = vmx_msr_high & 0x1fff; - vmcs = alloc_xenheap_pages(get_order(vmcs_size)); + vmcs = alloc_xenheap_pages(get_order_from_bytes(vmcs_size)); memset((char *)vmcs, 0, vmcs_size); /* don't remove this */ vmcs->vmcs_revision_id = vmx_msr_low; @@ -55,7 +55,7 @@ void free_vmcs(struct vmcs_struct *vmcs) { int order; - order = get_order(vmcs_size); + order = get_order_from_bytes(vmcs_size); free_xenheap_pages(vmcs, order); } @@ -76,8 +76,8 @@ static inline int construct_vmcs_controls(struct arch_vmx_struct *arch_vmx) error |= __vmwrite(VM_ENTRY_CONTROLS, MONITOR_VM_ENTRY_CONTROLS); /* need to use 0x1000 instead of PAGE_SIZE */ - io_bitmap_a = (void*) alloc_xenheap_pages(get_order(0x1000)); - io_bitmap_b = (void*) alloc_xenheap_pages(get_order(0x1000)); + io_bitmap_a = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000)); + io_bitmap_b = (void*) alloc_xenheap_pages(get_order_from_bytes(0x1000)); memset(io_bitmap_a, 0xff, 0x1000); /* don't bother debug port access */ clear_bit(PC_DEBUG_PORT, io_bitmap_a); diff --git a/xen/arch/x86/x86_32/mm.c b/xen/arch/x86/x86_32/mm.c index 002b9f8bc6..25c2ea7a7d 100644 --- a/xen/arch/x86/x86_32/mm.c +++ b/xen/arch/x86/x86_32/mm.c @@ -118,7 +118,8 @@ void __init paging_init(void) } /* Set up mapping cache for domain pages. */ - mapcache_order = get_order(MAPCACHE_MBYTES << (20 - PAGETABLE_ORDER)); + mapcache_order = get_order_from_bytes( + MAPCACHE_MBYTES << (20 - PAGETABLE_ORDER)); mapcache = alloc_xenheap_pages(mapcache_order); memset(mapcache, 0, PAGE_SIZE << mapcache_order); for ( i = 0; i < (MAPCACHE_MBYTES >> (L2_PAGETABLE_SHIFT - 20)); i++ ) diff --git a/xen/common/memory.c b/xen/common/memory.c index a744272539..45e9cc6852 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -154,7 +154,8 @@ long do_memory_op(int cmd, void *arg) reservation.nr_extents -= start_extent; if ( (reservation.address_bits != 0) && - (reservation.address_bits < (get_order(max_page) + PAGE_SHIFT)) ) + (reservation.address_bits < + (get_order_from_pages(max_page) + PAGE_SHIFT)) ) { if ( reservation.address_bits < 31 ) return -ENOMEM; diff --git a/xen/common/trace.c b/xen/common/trace.c index c5af36c4a0..7ba71a8009 100644 --- a/xen/common/trace.c +++ b/xen/common/trace.c @@ -66,7 +66,7 @@ void init_trace_bufs(void) } nr_pages = num_online_cpus() * opt_tbuf_size; - order = get_order(nr_pages * PAGE_SIZE); + order = get_order_from_pages(nr_pages); if ( (rawbuf = alloc_xenheap_pages(order)) == NULL ) { diff --git a/xen/common/xmalloc.c b/xen/common/xmalloc.c index 70c9c7fb29..5c0c02c754 100644 --- a/xen/common/xmalloc.c +++ b/xen/common/xmalloc.c @@ -86,7 +86,7 @@ static void *xmalloc_new_page(size_t size) static void *xmalloc_whole_pages(size_t size) { struct xmalloc_hdr *hdr; - unsigned int pageorder = get_order(size); + unsigned int pageorder = get_order_from_bytes(size); hdr = alloc_xenheap_pages(pageorder); if ( hdr == NULL ) @@ -159,7 +159,7 @@ void xfree(const void *p) /* Big allocs free directly. */ if ( hdr->size >= PAGE_SIZE ) { - free_xenheap_pages(hdr, get_order(hdr->size)); + free_xenheap_pages(hdr, get_order_from_bytes(hdr->size)); return; } diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 22524db86e..782ec814bf 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -627,7 +627,7 @@ static int __init debugtrace_init(void) if ( bytes == 0 ) return 0; - order = get_order(bytes); + order = get_order_from_bytes(bytes); debugtrace_buf = alloc_xenheap_pages(order); ASSERT(debugtrace_buf != NULL); diff --git a/xen/drivers/char/serial.c b/xen/drivers/char/serial.c index ad5ad5cde0..5eb0589443 100644 --- a/xen/drivers/char/serial.c +++ b/xen/drivers/char/serial.c @@ -366,8 +366,9 @@ void serial_register_uart(int idx, struct uart_driver *driver, void *uart) void serial_async_transmit(struct serial_port *port) { BUG_ON(!port->driver->tx_empty); - if ( !port->txbuf ) - port->txbuf = alloc_xenheap_pages(get_order(SERIAL_TXBUFSZ)); + if ( port->txbuf == NULL ) + port->txbuf = alloc_xenheap_pages( + get_order_from_bytes(SERIAL_TXBUFSZ)); } /* diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 71edad1530..d84a73a4f1 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -280,7 +280,7 @@ extern void paging_init(void); #ifndef __ASSEMBLY__ -static __inline__ int get_order(unsigned long size) +static inline int get_order_from_bytes(physaddr_t size) { int order; size = (size-1) >> PAGE_SHIFT; @@ -289,6 +289,15 @@ static __inline__ int get_order(unsigned long size) return order; } +static inline int get_order_from_pages(unsigned long nr_pages) +{ + int order; + nr_pages--; + for ( order = 0; nr_pages; order++ ) + nr_pages >>= 1; + return order; +} + /* Allocator functions for Xen pagetables. */ struct pfn_info *alloc_xen_pagetable(void); void free_xen_pagetable(struct pfn_info *pg); From 11a577fe4a3d98d672dc89fc1d12dca2477c9145 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 8 Sep 2005 17:29:02 +0000 Subject: [PATCH 07/13] grant_table.c reindent. Signed-off-by: Keir Fraser --- xen/common/grant_table.c | 208 +++++++++++++++++---------------------- 1 file changed, 91 insertions(+), 117 deletions(-) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 69ab0580b5..a5c56b4366 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -399,7 +399,7 @@ __gnttab_map_grant_ref( { int i; grant_mapping_t *new_mt; - grant_table_t *lgt = ld->grant_table; + grant_table_t *lgt = ld->grant_table; if ( (lgt->maptrack_limit << 1) > MAPTRACK_MAX_ENTRIES ) { @@ -437,9 +437,8 @@ __gnttab_map_grant_ref( ref, dom, dev_hst_ro_flags); #endif - if ( 0 <= ( rc = __gnttab_activate_grant_ref( ld, led, rd, ref, - dev_hst_ro_flags, - addr, &frame))) + if ( (rc = __gnttab_activate_grant_ref(ld, led, rd, ref, dev_hst_ro_flags, + addr, &frame)) >= 0 ) { /* * Only make the maptrack live _after_ writing the pte, in case we @@ -807,7 +806,8 @@ gnttab_donate(gnttab_donate_t *uop, unsigned int count) int i; int result = GNTST_okay; - for (i = 0; i < count; i++) { + for ( i = 0; i < count; i++ ) + { gnttab_donate_t *gop = &uop[i]; #if GRANT_DEBUG printk("gnttab_donate: i=%d mfn=%lx domid=%d gref=%08x\n", @@ -881,30 +881,6 @@ gnttab_donate(gnttab_donate_t *uop, unsigned int count) * headroom. Also, a domain mustn't have PGC_allocated * pages when it is dying. */ -#ifdef GRANT_DEBUG - if (unlikely(e->tot_pages >= e->max_pages)) { - printk("gnttab_dontate: no headroom tot_pages=%d max_pages=%d\n", - e->tot_pages, e->max_pages); - spin_unlock(&e->page_alloc_lock); - put_domain(e); - gop->status = result = GNTST_general_error; - break; - } - if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags))) { - printk("gnttab_donate: target domain is dying\n"); - spin_unlock(&e->page_alloc_lock); - put_domain(e); - gop->status = result = GNTST_general_error; - break; - } - if (unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle))) { - printk("gnttab_donate: gnttab_prepare_for_transfer fails.\n"); - spin_unlock(&e->page_alloc_lock); - put_domain(e); - gop->status = result = GNTST_general_error; - break; - } -#else ASSERT(e->tot_pages <= e->max_pages); if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags)) || unlikely(e->tot_pages == e->max_pages) || @@ -914,11 +890,10 @@ gnttab_donate(gnttab_donate_t *uop, unsigned int count) e->tot_pages, e->max_pages, gop->handle, e->d_flags); spin_unlock(&e->page_alloc_lock); put_domain(e); - /* XXX SMH: better error return here would be useful */ gop->status = result = GNTST_general_error; break; } -#endif + /* Okay, add the page to 'e'. */ if (unlikely(e->tot_pages++ == 0)) { get_knownalive_domain(e); @@ -957,38 +932,38 @@ do_grant_table_op( rc = -EFAULT; switch ( cmd ) - { - case GNTTABOP_map_grant_ref: - if ( unlikely(!array_access_ok( - uop, count, sizeof(gnttab_map_grant_ref_t))) ) - goto out; - rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count); - break; - case GNTTABOP_unmap_grant_ref: - if ( unlikely(!array_access_ok( - uop, count, sizeof(gnttab_unmap_grant_ref_t))) ) - goto out; - rc = gnttab_unmap_grant_ref((gnttab_unmap_grant_ref_t *)uop, - count); - break; - case GNTTABOP_setup_table: - rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count); - break; + { + case GNTTABOP_map_grant_ref: + if ( unlikely(!array_access_ok( + uop, count, sizeof(gnttab_map_grant_ref_t))) ) + goto out; + rc = gnttab_map_grant_ref((gnttab_map_grant_ref_t *)uop, count); + break; + case GNTTABOP_unmap_grant_ref: + if ( unlikely(!array_access_ok( + uop, count, sizeof(gnttab_unmap_grant_ref_t))) ) + goto out; + rc = gnttab_unmap_grant_ref( + (gnttab_unmap_grant_ref_t *)uop, count); + break; + case GNTTABOP_setup_table: + rc = gnttab_setup_table((gnttab_setup_table_t *)uop, count); + break; #if GRANT_DEBUG - case GNTTABOP_dump_table: - rc = gnttab_dump_table((gnttab_dump_table_t *)uop); - break; + case GNTTABOP_dump_table: + rc = gnttab_dump_table((gnttab_dump_table_t *)uop); + break; #endif - case GNTTABOP_donate: - if (unlikely(!array_access_ok(uop, count, - sizeof(gnttab_donate_t)))) - goto out; - rc = gnttab_donate(uop, count); - break; - default: - rc = -ENOSYS; - break; - } + case GNTTABOP_donate: + if (unlikely(!array_access_ok( + uop, count, sizeof(gnttab_donate_t)))) + goto out; + rc = gnttab_donate(uop, count); + break; + default: + rc = -ENOSYS; + break; + } out: UNLOCK_BIGLOCK(d); @@ -1021,17 +996,17 @@ gnttab_check_unmap( lgt = ld->grant_table; #if GRANT_DEBUG_VERBOSE - if ( ld->domain_id != 0 ) { - DPRINTK("Foreign unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n", - rd->domain_id, ld->domain_id, frame, readonly); - } + if ( ld->domain_id != 0 ) + DPRINTK("Foreign unref rd(%d) ld(%d) frm(%lx) flgs(%x).\n", + rd->domain_id, ld->domain_id, frame, readonly); #endif /* Fast exit if we're not mapping anything using grant tables */ if ( lgt->map_count == 0 ) return 0; - if ( get_domain(rd) == 0 ) { + if ( get_domain(rd) == 0 ) + { DPRINTK("gnttab_check_unmap: couldn't get_domain rd(%d)\n", rd->domain_id); return 0; @@ -1268,8 +1243,11 @@ grant_table_create( for ( i = 0; i < NR_GRANT_FRAMES; i++ ) { SHARE_PFN_WITH_DOMAIN( - virt_to_page((char *)(t->shared)+(i*PAGE_SIZE)), d); - set_pfn_from_mfn((virt_to_phys(t->shared) >> PAGE_SHIFT) + i, INVALID_M2P_ENTRY); + virt_to_page((char *)t->shared + (i * PAGE_SIZE)), + d); + set_pfn_from_mfn( + (virt_to_phys(t->shared) >> PAGE_SHIFT) + i, + INVALID_M2P_ENTRY); } /* Okay, install the structure. */ @@ -1306,57 +1284,53 @@ gnttab_release_dev_mappings(grant_table_t *gt) { map = >->maptrack[handle]; - if ( map->ref_and_flags & GNTMAP_device_map ) + if ( !(map->ref_and_flags & GNTMAP_device_map) ) + continue; + + dom = map->domid; + ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT; + + DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n", + handle, ref, map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom); + + if ( unlikely((rd = find_domain_by_id(dom)) == NULL) || + unlikely(ld == rd) ) { - dom = map->domid; - ref = map->ref_and_flags >> MAPTRACK_REF_SHIFT; - - DPRINTK("Grant release (%hu) ref:(%hu) flags:(%x) dom:(%hu)\n", - handle, ref, - map->ref_and_flags & MAPTRACK_GNTMAP_MASK, dom); - - if ( unlikely((rd = find_domain_by_id(dom)) == NULL) || - unlikely(ld == rd) ) - { - if ( rd != NULL ) - put_domain(rd); - - printk(KERN_WARNING "Grant release: No dom%d\n", dom); - continue; - } - - act = &rd->grant_table->active[ref]; - sha = &rd->grant_table->shared[ref]; - - spin_lock(&rd->grant_table->lock); - - if ( act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask) ) - { - frame = act->frame; - - if ( ( (act->pin & GNTPIN_hstw_mask) == 0 ) && - ( (act->pin & GNTPIN_devw_mask) > 0 ) ) - { - clear_bit(_GTF_writing, &sha->flags); - put_page_type(&frame_table[frame]); - } - - act->pin &= ~(GNTPIN_devw_mask | GNTPIN_devr_mask); - - if ( act->pin == 0 ) - { - clear_bit(_GTF_reading, &sha->flags); - map->ref_and_flags = 0; - put_page(&frame_table[frame]); - } - else - map->ref_and_flags &= ~GNTMAP_device_map; - } - - spin_unlock(&rd->grant_table->lock); - - put_domain(rd); + if ( rd != NULL ) + put_domain(rd); + printk(KERN_WARNING "Grant release: No dom%d\n", dom); + continue; } + + act = &rd->grant_table->active[ref]; + sha = &rd->grant_table->shared[ref]; + + spin_lock(&rd->grant_table->lock); + + if ( act->pin & (GNTPIN_devw_mask | GNTPIN_devr_mask) ) + { + frame = act->frame; + + if ( ( (act->pin & GNTPIN_hstw_mask) == 0 ) && + ( (act->pin & GNTPIN_devw_mask) > 0 ) ) + { + clear_bit(_GTF_writing, &sha->flags); + put_page_type(&frame_table[frame]); + } + + map->ref_and_flags &= ~GNTMAP_device_map; + act->pin &= ~(GNTPIN_devw_mask | GNTPIN_devr_mask); + if ( act->pin == 0 ) + { + clear_bit(_GTF_reading, &sha->flags); + map->ref_and_flags = 0; + put_page(&frame_table[frame]); + } + } + + spin_unlock(&rd->grant_table->lock); + + put_domain(rd); } } From 8ecda208694048a6926ec1f05ffc1a13e6c66a5d Mon Sep 17 00:00:00 2001 From: "iap10@freefall.cl.cam.ac.uk" Date: Thu, 8 Sep 2005 17:35:44 +0000 Subject: [PATCH 08/13] Fixes to sub 4GB allocator Signed-off-by: ian@xensource.com --- xen/common/memory.c | 3 ++- xen/include/asm-x86/page.h | 13 ++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/xen/common/memory.c b/xen/common/memory.c index a744272539..45e9cc6852 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -154,7 +154,8 @@ long do_memory_op(int cmd, void *arg) reservation.nr_extents -= start_extent; if ( (reservation.address_bits != 0) && - (reservation.address_bits < (get_order(max_page) + PAGE_SHIFT)) ) + (reservation.address_bits < + (get_order_from_pages(max_page) + PAGE_SHIFT)) ) { if ( reservation.address_bits < 31 ) return -ENOMEM; diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 71edad1530..2473b8cbf3 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -280,7 +280,7 @@ extern void paging_init(void); #ifndef __ASSEMBLY__ -static __inline__ int get_order(unsigned long size) +static inline int get_order_from_bytes(physaddr_t size) { int order; size = (size-1) >> PAGE_SHIFT; @@ -289,6 +289,17 @@ static __inline__ int get_order(unsigned long size) return order; } +static inline int get_order_from_pages(unsigned long nr_pages) +{ + int order; + nr_pages--; + for ( order = 0; nr_pages; order++ ) + nr_pages >>= 1; + return order; +} + +#define get_order(s) get_order_from_bytes(s) + /* Allocator functions for Xen pagetables. */ struct pfn_info *alloc_xen_pagetable(void); void free_xen_pagetable(struct pfn_info *pg); From cab0ef71c3013bdb8d8cae2ab3529724adbd3291 Mon Sep 17 00:00:00 2001 From: "iap10@freefall.cl.cam.ac.uk" Date: Thu, 8 Sep 2005 17:36:23 +0000 Subject: [PATCH 09/13] Improved "PGDs must be under 4GB" handling for PAE. Signed-off-by: ian@xensource.com --- tools/libxc/xc_domain.c | 54 ++++++++++++++++++++++++++----- tools/libxc/xc_linux_build.c | 15 ++++++++- tools/libxc/xc_linux_restore.c | 2 +- tools/libxc/xc_private.c | 18 +++++++++++ tools/libxc/xenctrl.h | 14 ++++++-- tools/python/xen/lowlevel/xc/xc.c | 7 +++- tools/python/xen/xend/image.py | 5 +-- 7 files changed, 100 insertions(+), 15 deletions(-) diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 2c3a3a998c..7181518380 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -262,28 +262,66 @@ int xc_domain_setmaxmem(int xc_handle, int xc_domain_memory_increase_reservation(int xc_handle, u32 domid, - unsigned long mem_kb, + unsigned long nr_extents, unsigned int extent_order, - unsigned int address_bits) + unsigned int address_bits, + unsigned long *extent_start) { int err; - unsigned int npages = mem_kb / (PAGE_SIZE/1024); struct xen_memory_reservation reservation = { - .nr_extents = npages, - .extent_order = extent_order, + .extent_start = extent_start, /* may be NULL */ + .nr_extents = nr_extents, + .extent_order = extent_order, .address_bits = address_bits, .domid = domid }; err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation); - if (err == npages) + if (err == nr_extents) return 0; if (err > 0) { - fprintf(stderr,"Failed alocation for dom %d : %d pages order %d addr_bits %d\n", - domid, npages, extent_order, address_bits); + fprintf(stderr,"Failed alocation for dom %d : %ld pages order %d addr_bits %d\n", + domid, nr_extents, extent_order, address_bits); errno = ENOMEM; err = -1; } return err; } + +int xc_domain_memory_decrease_reservation(int xc_handle, + u32 domid, + unsigned long nr_extents, + unsigned int extent_order, + unsigned long *extent_start) +{ + int err; + struct xen_memory_reservation reservation = { + .extent_start = extent_start, + .nr_extents = nr_extents, + .extent_order = extent_order, + .address_bits = 0, + .domid = domid + }; + + if (extent_start == NULL) + { + fprintf(stderr,"decrease_reservation extent_start is NULL!\n"); + errno = EINVAL; + err = -1; + goto out; + } + + err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation); + if (err == nr_extents) + return 0; + + if (err > 0) { + fprintf(stderr,"Failed de-alocation for dom %d : %ld pages order %d\n", + domid, nr_extents, extent_order); + errno = EBUSY; + err = -1; + } +out: + return err; +} diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 89a71a4695..d8bd76d26f 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -136,11 +136,24 @@ static int setup_pg_tables_pae(int xc_handle, u32 dom, /* First allocate page for page dir. */ ppt_alloc = (vpt_start - dsi_v_start) >> PAGE_SHIFT; + + if ( page_array[ppt_alloc] > 0xfffff ) + { + unsigned long nmfn; + nmfn = xc_make_page_below_4G( xc_handle, dom, page_array[ppt_alloc] ); + if ( nmfn == 0 ) + { + fprintf(stderr, "Couldn't get a page below 4GB :-(\n"); + goto error_out; + } + page_array[ppt_alloc] = nmfn; + } + alloc_pt(l3tab, vl3tab); vl3e = &vl3tab[l3_table_offset_pae(dsi_v_start)]; ctxt->ctrlreg[3] = l3tab; - if(l3tab>0xfffff000) + if(l3tab>0xfffff000ULL) { fprintf(stderr,"L3TAB = %llx above 4GB!\n",l3tab); goto error_out; diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index d953ad2a48..f1fb60db8d 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -149,7 +149,7 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns, } err = xc_domain_memory_increase_reservation(xc_handle, dom, - nr_pfns * PAGE_SIZE / 1024, 0, 0); //FIX ME + nr_pfns, 0, 0, NULL); if (err != 0) { ERR("Failed to increase reservation by %lx\n", nr_pfns * PAGE_SIZE / 1024); diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 58392cc07e..5a1d78f9d5 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -427,3 +427,21 @@ int xc_version(int xc_handle, int cmd, void *arg) { return do_xen_version(xc_handle, cmd, arg); } + +unsigned long xc_make_page_below_4G(int xc_handle, u32 domid, + unsigned long mfn) +{ + unsigned long new_mfn; + if ( xc_domain_memory_decrease_reservation( + xc_handle, domid, 1, 0, &mfn ) != 1 ) + { + fprintf(stderr,"xc_make_page_below_4G decrease failed. mfn=%lx\n",mfn); + return 0; + } + if ( xc_domain_memory_increase_reservation( xc_handle, domid, 1, 0, 32, &new_mfn ) != 1 ) + { + fprintf(stderr,"xc_make_page_below_4G increase failed. mfn=%lx\n",mfn); + return 0; + } + return new_mfn; +} diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 006e647825..41174c1feb 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -387,9 +387,19 @@ int xc_domain_setmaxmem(int xc_handle, int xc_domain_memory_increase_reservation(int xc_handle, u32 domid, - unsigned long mem_kb, + unsigned long nr_extents, unsigned int extent_order, - unsigned int address_bits); + unsigned int address_bits, + unsigned long *extent_start); + +int xc_domain_memory_decrease_reservation(int xc_handle, + u32 domid, + unsigned long nr_extents, + unsigned int extent_order, + unsigned long *extent_start); + +unsigned long xc_make_page_below_4G(int xc_handle, u32 domid, + unsigned long mfn); typedef dom0_perfc_desc_t xc_perfc_desc_t; /* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */ diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index e4a96be580..d2c132ed8b 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -842,6 +842,7 @@ static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self, u32 dom; unsigned long mem_kb; unsigned int extent_order = 0 , address_bits = 0; + unsigned long nr_extents; static char *kwd_list[] = { "dom", "mem_kb", "extent_order", "address_bits", NULL }; @@ -849,8 +850,12 @@ static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self, &dom, &mem_kb, &extent_order, &address_bits) ) return NULL; + /* round down to nearest power of 2. Assume callers using extent_order>0 + know what they are doing */ + nr_extents = (mem_kb / (XC_PAGE_SIZE/1024)) >> extent_order; if ( xc_domain_memory_increase_reservation(xc->xc_handle, dom, - mem_kb, extent_order, address_bits) ) + nr_extents, extent_order, + address_bits, NULL) ) return PyErr_SetFromErrno(xc_error); Py_INCREF(zero); diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 4403e8d886..8b3b646afa 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -160,8 +160,9 @@ class ImageHandler: try: # Give the domain some memory below 4GB - lmem_kb = 4096 - xc.domain_memory_increase_reservation(dom, min(lmem_kb,mem_kb), 0, 32) + lmem_kb = 0 + if lmem_kb > 0: + xc.domain_memory_increase_reservation(dom, min(lmem_kb,mem_kb), 0, 32) if mem_kb > lmem_kb: xc.domain_memory_increase_reservation(dom, mem_kb-lmem_kb, 0, 0) except: From 94a7d0b79cf5f3b0fc5cb25b7c4edb7b117c5a0a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 8 Sep 2005 17:36:37 +0000 Subject: [PATCH 10/13] Build fix. --- xen/common/grant_table.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index a5c56b4366..d444fb4136 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -815,19 +815,24 @@ gnttab_donate(gnttab_donate_t *uop, unsigned int count) #endif page = &frame_table[gop->mfn]; - if (unlikely(IS_XEN_HEAP_FRAME(page))) { + if ( unlikely(IS_XEN_HEAP_FRAME(page))) + { printk("gnttab_donate: xen heap frame mfn=%lx\n", (unsigned long) gop->mfn); gop->status = GNTST_bad_virt_addr; continue; } - if (unlikely(!pfn_valid(page_to_pfn(page)))) { + + if ( unlikely(!pfn_valid(page_to_pfn(page))) ) + { printk("gnttab_donate: invalid pfn for mfn=%lx\n", (unsigned long) gop->mfn); gop->status = GNTST_bad_virt_addr; continue; } - if (unlikely((e = find_domain_by_id(gop->domid)) == NULL)) { + + if ( unlikely((e = find_domain_by_id(gop->domid)) == NULL) ) + { printk("gnttab_donate: can't find domain %d\n", gop->domid); gop->status = GNTST_bad_domain; continue; @@ -881,13 +886,14 @@ gnttab_donate(gnttab_donate_t *uop, unsigned int count) * headroom. Also, a domain mustn't have PGC_allocated * pages when it is dying. */ - ASSERT(e->tot_pages <= e->max_pages); - if (unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags)) || - unlikely(e->tot_pages == e->max_pages) || - unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle))) { - printk("gnttab_donate: Transferee has no reservation headroom (%d," - "%d) or provided a bad grant ref (%08x) or is dying (%p)\n", - e->tot_pages, e->max_pages, gop->handle, e->d_flags); + if ( unlikely(test_bit(DOMFLAGS_DYING, &e->domain_flags)) || + unlikely(e->tot_pages >= e->max_pages) || + unlikely(!gnttab_prepare_for_transfer(e, d, gop->handle)) ) + { + DPRINTK("gnttab_donate: Transferee has no reservation headroom " + "(%d,%d) or provided a bad grant ref (%08x) or " + "is dying (%lx)\n", + e->tot_pages, e->max_pages, gop->handle, e->domain_flags); spin_unlock(&e->page_alloc_lock); put_domain(e); gop->status = result = GNTST_general_error; @@ -895,9 +901,8 @@ gnttab_donate(gnttab_donate_t *uop, unsigned int count) } /* Okay, add the page to 'e'. */ - if (unlikely(e->tot_pages++ == 0)) { + if ( unlikely(e->tot_pages++ == 0) ) get_knownalive_domain(e); - } list_add_tail(&page->list, &e->page_list); page_set_owner(page, e); @@ -913,6 +918,7 @@ gnttab_donate(gnttab_donate_t *uop, unsigned int count) gop->status = GNTST_okay; } + return result; } From 9c3c47ec6e576f3a90d6ea9b3c21e4fdeefa01b7 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 8 Sep 2005 17:47:48 +0000 Subject: [PATCH 11/13] No need to qsort the pfn array in domu builder. --- tools/libxc/xc_linux_build.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index d8bd76d26f..1d0f6d7388 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -283,11 +283,6 @@ static int setup_pg_tables_64(int xc_handle, u32 dom, } #endif -static int compare (const void * a, const void * b) -{ - return ( *(long*)a - *(long*)b ); -} - #ifdef __ia64__ #include /* for FPSR_DEFAULT */ static int setup_guest(int xc_handle, @@ -501,9 +496,6 @@ static int setup_guest(int xc_handle, goto error_out; } - qsort( page_array, nr_pages, sizeof(*page_array), compare ); - - (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array, &dsi); From 7901c856f1f50f64de391decce1c324c94b9163c Mon Sep 17 00:00:00 2001 From: "iap10@firebug.cl.cam.ac.uk" Date: Thu, 8 Sep 2005 19:14:51 +0000 Subject: [PATCH 12/13] Test CD needs devfs Signed-off-by: ian@xensource.com --- linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 index 21eabb7c38..6b9a05feb0 100644 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 @@ -2202,7 +2202,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="ascii" CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y CONFIG_SYSFS=y -# CONFIG_DEVFS_FS is not set +CONFIG_DEVFS_FS=y CONFIG_DEVPTS_FS_XATTR=y CONFIG_DEVPTS_FS_SECURITY=y CONFIG_TMPFS=y From 9ead829c58b5d4b745320dd8a89882ff39293594 Mon Sep 17 00:00:00 2001 From: "iap10@firebug.cl.cam.ac.uk" Date: Thu, 8 Sep 2005 20:39:58 +0000 Subject: [PATCH 13/13] Bug fix on x86_64 increase_reservation Signed-off-by: ian@xensource.com --- tools/python/xen/lowlevel/xc/xc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index d2c132ed8b..531b7a7b1c 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -846,7 +846,7 @@ static PyObject *pyxc_domain_memory_increase_reservation(PyObject *self, static char *kwd_list[] = { "dom", "mem_kb", "extent_order", "address_bits", NULL }; - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii|ii", kwd_list, + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "il|ii", kwd_list, &dom, &mem_kb, &extent_order, &address_bits) ) return NULL;