On Thu, 2006-11-02 at 16:01 +0000, Kieran Mansley wrote:
> I'm having a couple of problems dealing with pages in dom0 that have
> been mapped via a grant from domU, and wondered if anyone can confirm my
> suspicions and suggest a way round this.
>
> I pass a grant from domU to dom0, and map it in to dom0 using
> xenbus_map_ring_valloc(). This gives me a "struct vm_struct" which
> isn't terribly useful as most of it isn't filled out, but it does have a
> virtual address for the page in dom0. I need to pass this page to a PCI
> device, and so would like to use something like pci_map_single() (or
> dma_map_page()) to convert this virtual address into a bus address.
> However, neither of these seem to be working as one might hope: they
> always return the same value regardless of the address you pass in (at
> least for the valid addresses that I've tried).
As a follow-up to my question (to which I would still welcome any
ideas!), I've experimented with using the GNTMAP_contains_pte flag to
the HYPERVISOR_grant_table_op by modifying xenbus_map_ring_valloc() as
follows. After the call to alloc_vm_area, replace the newly allocated
area->addr with a call to kzalloc() to get a region of virtual address
space that actually has something backing it. I call
create_lookup_pte_addr() at this point to ensure the page tables are set
up properly and get the page table entry. Then, call the
HYPERVISOR_grant_table_op as before, but add the GNTMAP_contains_pte
flag and give it the address of the pte:
struct vm_struct *xenbus_map_ring_valloc(struct xenbus_device *dev,
int gnt_ref)
{
struct gnttab_map_grant_ref op;
struct vm_struct *area;
int ret;
uint64_t ptep;
area = alloc_vm_area(PAGE_SIZE);
if (!area)
return ERR_PTR(-ENOMEM);
/* Added code starts here */
area->addr = kzalloc(PAGE_SIZE, GFP_KERNEL);
ret = create_lookup_pte_addr(&init_mm, area->addr, &ptep);
if(ret){
printk("%s: Couldn't get a pte addr!\n", __FUNCTION__);
return ERR_PTR(-ENOMEM);
}
/* Added code ends here */
/* Changed to modify pte rather than providing virtual address */
gnttab_set_map_op(&op, ptep, GNTMAP_host_map | GNTMAP_contains_pte,
gnt_ref, dev->otherend_id);
lock_vm_area(area);
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
unlock_vm_area(area);
The rest of the function is unchanged. This changes are clearly a dirty
hack, but at the moment I'm interested in finding out what is wrong
rather than getting something pretty!
This change seems to result in the grant getting mapped in and me being
able to get a different "struct page" and bus address for each granted
page, rather than the same one each time.
This seems to confirm my theory that the normal call to map the grant is
deficient in the way it deals with the page tables in dom0. Before I
file a bug for this, would anyone like to comment, or point out what I'm
doing wrong?
Thanks
Kieran
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|