ia64/xen-unstable

changeset 9506:90813b66c3cf

[IA64] get_pfn_list workaround

As we know, the mechanism for hypervisor to pass parameter through pointer
is not complete. Hypervisor use copy_from/to_user functions to copy parameter
to hypervisor and copy result to user, if there is a tlb miss happening and
hypervisor can't handled this. This hypercall fails, there is no mechanism to
handle this failure, that may cause domain crash. Get_pfn_list hypercall copy
large data from hypervisor to user, it is easy to trigger this issue when
creating VTI-domain.

If fails, Get_pfn_list returns the number of pfn entries, and this patch will
Dummy access parameter memory block to cause this tlb mapping tracked by
Hypervisor, then continue to do get_pfn_list.

It's a workaround before we design a new mechanism of passing parameter thr
pointer.

Signed-off-by: Anthony Xu <anthony.xu@intel.com>
author awilliam@xenbuild.aw
date Mon Apr 10 15:13:42 2006 -0600 (2006-04-10)
parents 0a7e619a248f
children 67b24fc635ae
files tools/libxc/xc_ia64_stubs.c
line diff
     1.1 --- a/tools/libxc/xc_ia64_stubs.c	Mon Apr 10 14:54:35 2006 -0600
     1.2 +++ b/tools/libxc/xc_ia64_stubs.c	Mon Apr 10 15:13:42 2006 -0600
     1.3 @@ -48,6 +48,12 @@ xc_plan9_build(int xc_handle,
     1.4      PERROR("xc_plan9_build not implemented\n");
     1.5      return -1;
     1.6  }
     1.7 +/*  
     1.8 +    VMM uses put_user to copy pfn_list to guest buffer, this maybe fail,
     1.9 +    VMM don't handle this now.
    1.10 +    This method will touch guest buffer to make sure the buffer's mapping
    1.11 +    is tracked by VMM,
    1.12 +  */
    1.13  
    1.14  int xc_ia64_get_pfn_list(int xc_handle,
    1.15                           uint32_t domid, 
    1.16 @@ -56,27 +62,48 @@ int xc_ia64_get_pfn_list(int xc_handle,
    1.17                           unsigned int nr_pages)
    1.18  {
    1.19      dom0_op_t op;
    1.20 -    int ret;
    1.21 -    unsigned long max_pfns = ((unsigned long)start_page << 32) | nr_pages;
    1.22 -
    1.23 -    op.cmd = DOM0_GETMEMLIST;
    1.24 -    op.u.getmemlist.domain   = (domid_t)domid;
    1.25 -    op.u.getmemlist.max_pfns = max_pfns;
    1.26 -    op.u.getmemlist.buffer   = pfn_buf;
    1.27 +    int num_pfns,ret;
    1.28 +    unsigned int __start_page, __nr_pages;
    1.29 +    unsigned long max_pfns;
    1.30 +    unsigned long *__pfn_buf;
    1.31 +    __start_page = start_page;
    1.32 +    __nr_pages = nr_pages;
    1.33 +    __pfn_buf = pfn_buf;
    1.34 +  
    1.35 +    while(__nr_pages){
    1.36 +        max_pfns = ((unsigned long)__start_page << 32) | __nr_pages;
    1.37 +        op.cmd = DOM0_GETMEMLIST;
    1.38 +        op.u.getmemlist.domain   = (domid_t)domid;
    1.39 +        op.u.getmemlist.max_pfns = max_pfns;
    1.40 +        op.u.getmemlist.buffer   = __pfn_buf;
    1.41  
    1.42 -    if ( (max_pfns != -1UL)
    1.43 -		&& mlock(pfn_buf, nr_pages * sizeof(unsigned long)) != 0 )
    1.44 -    {
    1.45 -        PERROR("Could not lock pfn list buffer");
    1.46 -        return -1;
    1.47 -    }    
    1.48 +        if ( (max_pfns != -1UL)
    1.49 +		    && mlock(__pfn_buf, __nr_pages * sizeof(unsigned long)) != 0 )
    1.50 +        {
    1.51 +            PERROR("Could not lock pfn list buffer");
    1.52 +            return -1;
    1.53 +        }    
    1.54 +
    1.55 +        ret = do_dom0_op(xc_handle, &op);
    1.56 +
    1.57 +        if (max_pfns != -1UL)
    1.58 +        	(void)munlock(__pfn_buf, __nr_pages * sizeof(unsigned long));
    1.59  
    1.60 -    ret = do_dom0_op(xc_handle, &op);
    1.61 +        if (max_pfns == -1UL)
    1.62 +            return 0;
    1.63 +        
    1.64 +        num_pfns = op.u.getmemlist.num_pfns;
    1.65 +        __start_page += num_pfns;
    1.66 +        __nr_pages -= num_pfns;
    1.67 +        __pfn_buf += num_pfns;
    1.68  
    1.69 -    if (max_pfns != -1UL)
    1.70 -    	(void)munlock(pfn_buf, nr_pages * sizeof(unsigned long));
    1.71 -
    1.72 -    return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
    1.73 +        if (ret < 0) 
    1.74 +            // dummy write to make sure this tlb mapping is tracked by VMM 
    1.75 +            *__pfn_buf = 0;
    1.76 +        else 
    1.77 +            return nr_pages;    
    1.78 +    }    
    1.79 +    return nr_pages;
    1.80  }
    1.81  
    1.82  long xc_get_max_pages(int xc_handle, uint32_t domid)