[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] Re: Linux Stubdom Problem
On Wed, 14 Sep 2011, Jiageng Yu wrote: > Hi Stefano, > > I just have a prototype of vram mapping and test it now. The > implementation of linux-stubdom kernel part is as follows. > xen_remap_domain_mfn_range2 function maps foreign dom's physical > address into linux kernel space. It is similar to > xen_remap_domain_mfn_range. But xen_remap_domain_mfn_range is used to > map foreign pages into linux user space. > > But the page info seems wrong after executing xen_remap_domain_mfn_range2. > > struct page *page=pfn_to_page(vmalloc_to_pfn(info->fb)); > > The page->_count = 0xc2c2c2c2. It is very strange. > > Did I do the right thing? > use page_address instead of pfn_to_page to find the struct page > Greeting. > > Jiageng Yu. > > > diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c > index 204e3ba..72a7808 100644 > --- a/arch/x86/xen/mmu.c > +++ b/arch/x86/xen/mmu.c > @@ -2693,6 +2693,73 @@ out: > } > EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range); > > +int xen_remap_domain_mfn_range2(unsigned long addr,unsigned long gpfn, > + int nr, unsigned domid) > +{ > + struct remap_data rmd; > + struct mmu_update mmu_update[REMAP_BATCH_SIZE]; > + int level,i,batch,nr_page = nr; > + unsigned long range; > + int err = 0; > + unsigned long vaddr,base_addr = addr; > + pte_t pte,*ptep; > + > + rmd.mfn = gpfn; > + rmd.prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | > _PAGE_IOMAP); > + > + while(nr_page) { > + batch = min(REMAP_BATCH_SIZE, nr); > + range = (unsigned long)batch << PAGE_SHIFT; > + > + rmd.mmu_update = mmu_update; > + > + for(i=0; i < batch; i++){ > + pte = pte_mkspecial(pfn_pte(rmd.mfn++, rmd.prot)); > + vaddr = base_addr + i*PAGE_SIZE; > + ptep = lookup_address(vaddr, &level); you need to check if ptep is valid here and the level is PG_LEVEL_4K > + rmd.mmu_update->ptr = arbitrary_virt_to_machine(ptep).maddr | > + MMU_NORMAL_PT_UPDATE; you can use pte_mfn(*ptep) instead of arbitrary_virt_to_machine > + rmd.mmu_update->val = pte_val_ma(pte); > + rmd.mmu_update++; > + } > + > + err = -EFAULT; > + if(HYPERVISOR_mmu_update(mmu_update, batch, NULL, domid) < 0) > + goto out; > + > + nr_page -= batch; > + base_addr += range; > + } > + > + err = 0; > + > + base_addr = addr; > + for(i=0; i < nr; i++){ > + vaddr = base_addr + i*PAGE_SIZE; > + set_phys_to_machine(vmalloc_to_pfn(vaddr), > + arbitrary_virt_to_machine(vaddr).maddr >> PAGE_SHIFT); > + } The second argument (mfn) to set_phys_to_machine is wrong: arbitrary_virt_to_machine ends up calling virt_to_machine if virt_addr_valid. You need to manually call pte_mfn: /* the ptep content has been updated by Xen so we can lookup the foreign * mfn from the pte now */ pte = lookup_address(vaddr, &level); BUG_ON(pte == NULL); offset = vaddr & ~PAGE_MASK; mfn = XMADDR(((phys_addr_t)pte_mfn(*pte) << PAGE_SHIFT) + offset); > + > +out: > + flush_tlb_all(); > + return err; > +} > +EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_range2); the name should be changed to xen_remap_foreign_gpfn_range > #ifdef CONFIG_XEN_PVHVM > static void xen_hvm_exit_mmap(struct mm_struct *mm) > { > diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c > index dc72563..82da2ee 100644 > --- a/drivers/video/xen-fbfront.c > +++ b/drivers/video/xen-fbfront.c > @@ -25,8 +25,12 @@ > #include <linux/module.h> > #include <linux/vmalloc.h> > #include <linux/mm.h> > +#include <linux/sched.h> > +#include <asm/pgtable.h> > +#include <asm/page.h> > > #include <asm/xen/hypervisor.h> > +#include <asm/xen/page.h> > > #include <xen/xen.h> > #include <xen/events.h> > @@ -34,6 +38,7 @@ > #include <xen/interface/io/fbif.h> > #include <xen/interface/io/protocols.h> > #include <xen/xenbus.h> > +#include <xen/xen-ops.h> > > struct xenfb_info { > unsigned char *fb; > @@ -62,6 +67,12 @@ module_param_array(video, int, NULL, 0); > MODULE_PARM_DESC(video, > "Video memory size in MB, width, height in pixels (default 2,800,600)"); > > +static unsigned long foreign_vaddr = 0; > +module_param(foreign_vaddr, ulong, S_IRUGO); > + > +static unsigned long foreign_domid = 0; > +module_param(foreign_domid, ulong, S_IRUGO); > + > static void xenfb_make_preferred_console(void); > static int xenfb_remove(struct xenbus_device *); > static void xenfb_init_shared_page(struct xenfb_info *, struct fb_info *); > @@ -398,7 +408,17 @@ static int __devinit xenfb_probe(struct xenbus_device > *dev, > if (info->fb == NULL) > goto error_nomem; > memset(info->fb, 0, fb_size); > - > + if((foreign_vaddr != 0) && (foreign_domid != 0)){ > + ret = xen_remap_domain_mfn_range2((unsigned long)(info->fb), > + foreign_vaddr >> PAGE_SHIFT, > + fb_size >> PAGE_SHIFT, foreign_domid); you should rename foreign_vaddr to foreign_gpfn and pass the gpfn value that is the ram_addr (page shifted) passed to xen_ram_alloc in qemu. > + if(ret < 0){ > + printk("Can not remap vram of hvm guest.\n"); > + goto error; > + } > + } > info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT; > > info->mfns = vmalloc(sizeof(unsigned long) * info->nr_pages); > diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h > index 4349e89..1554531 100644 > --- a/include/xen/xen-ops.h > +++ b/include/xen/xen-ops.h > @@ -20,6 +20,10 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, > unsigned long mfn, int nr, > pgprot_t prot, unsigned domid); > > +int xen_remap_domain_mfn_range2(unsigned long addr,unsigned long mfn, > + int nr, unsigned domid); > extern unsigned long *xen_contiguous_bitmap; > int xen_create_contiguous_region(unsigned long vstart, unsigned int order, > unsigned int address_bits); > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |