[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH V2] tools/libxc, xen/x86: Added xc_set_mem_access_multi()



On 09/02/2016 01:02 PM, Jan Beulich wrote:
>>>> On 02.09.16 at 10:51, <rcojocaru@xxxxxxxxxxxxxxx> wrote:
>> Changes since V1 / RFC:
>>  - Renamed xc_set_mem_access_sparse() to xc_set_mem_access_multi(),
>>    and XENMEM_access_op_set_access_sparse to
>>    XENMEM_access_op_set_access_multi.
>>  - Renamed the 'nr' parameter to 'size'.
> 
> Why?

Tamas suggested it, size sounded more intuitive to him. I have no
problem with either nr or size.

>>  - Wrapped long line in the implementation of xc_set_mem_access_multi().
>>  - Factored out common code in _p2m_set_mem_access() (and modified
>>    p2m_set_altp2m_mem_access() in the process, to take an unsigned
>>    long argument instead of a gfn_t).
>>  - Factored out xenmem_access_t to p2m_access_t conversion code in
>>    p2m_xenmem_access_to_p2m_access().
>>  - Added hypercall continuation support.
>>  - Added compat translation support.
>>  - No longer allocating buffers (now using copy_from_guest_offset()).
>>  - Added support for setting an array of access restrictions, as
>>    suggested by Tamas Lengyel.
>>  - This patch incorporates Jan Beulich's "memory: fix compat handling
>>    of XENMEM_access_op".
> 
> I'm not sure that's okay; I'd have preferred you make the other
> patch a prereq (not the least because that one may want
> backporting, while this one certainly won't). In no event should
> such a bug fix go without mentioning in the commit message.

I agree, this is here simply because looking at the state of staging,
the patch hadn't yet made it in, and I was trying to be efficient and
have an intermediate review anyway. I'll manually apply your patch
before mine and remove that code from this patch.

>> @@ -1772,13 +1773,12 @@ bool_t p2m_mem_access_check(paddr_t gpa, unsigned 
>> long gla,
>>  static inline
>>  int p2m_set_altp2m_mem_access(struct domain *d, struct p2m_domain *hp2m,
>>                                struct p2m_domain *ap2m, p2m_access_t a,
>> -                              gfn_t gfn)
>> +                              unsigned long gfn_l)
>>  {
> 
> I'm not really happy about such a step backwards.

I'll keep p2m_set_altp2m_mem_access() as it is then. I just thought that
going from unsigned long to gfn_t just to have to go back to unsigned
long slightly clutters up the code, but it's certainly not a huge
difference.

>> @@ -1811,21 +1811,39 @@ int p2m_set_altp2m_mem_access(struct domain *d, 
>> struct p2m_domain *hp2m,
>>                           (current->domain != d));
>>  }
>>  
>> -/*
>> - * Set access type for a region of gfns.
>> - * If gfn == INVALID_GFN, sets the default access type.
>> - */
>> -long p2m_set_mem_access(struct domain *d, gfn_t gfn, uint32_t nr,
>> -                        uint32_t start, uint32_t mask, xenmem_access_t 
>> access,
>> -                        unsigned int altp2m_idx)
>> +static inline
>> +int _p2m_set_mem_access(struct domain *d, struct p2m_domain *p2m,
> 
> Considering the file we're in, can't this just be set_mem_access()?

Of course, I'll rename it.

> Also I'd leave the inlining decision completely to the compiler.

I took that cue from p2m_set_altp2m_mem_access() above. I'll remove the
inline.

>> +                        struct p2m_domain *ap2m, p2m_access_t a,
>> +                        unsigned long gfn_l)
>>  {
>> -    struct p2m_domain *p2m = p2m_get_hostp2m(d), *ap2m = NULL;
>> -    p2m_access_t a, _a;
>> -    p2m_type_t t;
>> -    mfn_t mfn;
>> -    unsigned long gfn_l;
>> -    long rc = 0;
>> +    int rc;
>>  
>> +    if ( ap2m )
>> +    {
>> +        rc = p2m_set_altp2m_mem_access(d, p2m, ap2m, a, gfn_l);
>> +        /* If the corresponding mfn is invalid we will want to just skip it 
>> */
>> +        if ( rc && rc != -ESRCH )
>> +            return rc;
> 
> If you just converted -ESRCH to 0 here, you could then ...
> 
>> +    }
>> +    else
>> +    {
>> +        mfn_t mfn;
>> +        p2m_access_t _a;
>> +        p2m_type_t t;
>> +
>> +        mfn = p2m->get_entry(p2m, gfn_l, &t, &_a, 0, NULL, NULL);
>> +        rc = p2m->set_entry(p2m, gfn_l, mfn, PAGE_ORDER_4K, t, a, -1);
>> +        return rc;
> 
> ... ditch this extra return path and ...
> 
>> +    }
>> +
>> +    return 0;
> 
> ... have both cases come here.

I'll do that.

>> @@ -1851,17 +1897,8 @@ long p2m_set_mem_access(struct domain *d, gfn_t gfn, 
>> uint32_t nr,
>>          ap2m = d->arch.altp2m_p2m[altp2m_idx];
>>      }
>>  
>> -    switch ( access )
>> -    {
>> -    case 0 ... ARRAY_SIZE(memaccess) - 1:
>> -        a = memaccess[access];
>> -        break;
>> -    case XENMEM_access_default:
>> -        a = p2m->default_access;
>> -        break;
>> -    default:
>> +    if ( p2m_xenmem_access_to_p2m_access(p2m, access, &a) )
>>          return -EINVAL;
> 
> Either you make the helper function return bool, or you pass on
> whatever value it returned instead of assuming it's -EINVAL.

Fair enough, I'll return bool.

>> +long p2m_set_mem_access_multi(struct domain *d,
>> +                              XEN_GUEST_HANDLE(uint64_t) pfn_list,
>> +                              XEN_GUEST_HANDLE(uint8) access_list,
>> +                              uint32_t size, uint32_t start, uint32_t mask,
>> +                              unsigned int altp2m_idx)
>> +{
>> +    struct p2m_domain *p2m = p2m_get_hostp2m(d), *ap2m = NULL;
>> +    long rc = 0;
>> +
>> +    /* altp2m view 0 is treated as the hostp2m */
>> +    if ( altp2m_idx )
>> +    {
>> +        if ( altp2m_idx >= MAX_ALTP2M ||
>> +             d->arch.altp2m_eptp[altp2m_idx] == mfn_x(INVALID_MFN) )
>> +            return -EINVAL;
>> +
>> +        ap2m = d->arch.altp2m_p2m[altp2m_idx];
>> +    }
>> +
>> +    p2m_lock(p2m);
>> +    if ( ap2m )
>> +        p2m_lock(ap2m);
>> +
>> +    while ( start < size )
>> +    {
>> +        p2m_access_t a;
>> +
>> +        uint8_t access;
>> +        uint64_t gfn_l;
> 
> Stray blank line between declarations.

Will remove it.

>> @@ -320,6 +321,23 @@ int compat_memory_op(unsigned int cmd, 
>> XEN_GUEST_HANDLE_PARAM(void) compat)
>>              break;
>>          }
>>  
>> +        case XENMEM_access_op:
>> +        {
>> +#define XLAT_mem_access_op_HNDL_pfn_list(_d_, _s_) \
>> +            guest_from_compat_handle((_d_)->pfn_list, (_s_)->pfn_list)
>> +#define XLAT_mem_access_op_HNDL_access_list(_d_, _s_) \
>> +            guest_from_compat_handle((_d_)->access_list, (_s_)->access_list)
>> +
>> +            XLAT_mem_access_op(nat.mao, &cmp.mao);
>> +
>> +#undef XLAT_mem_access_op_HNDL_pfn_list
>> +#undef XLAT_mem_access_op_HNDL_access_list
>> +
>> +            return mem_access_memop(cmd,
>> +                                    guest_handle_cast(compat,
>> +                                                      xen_mem_access_op_t));
>> +        }
> 
> You translate into native format, but then cast the compat handle
> to its native counterpart type. Such casting is okay only when
> accompanied by a respectively invoked CHECK_* macro. Please
> follow the model other code here uses.

I'll follow the model.

> And reviewing this I notice that my earlier bug fix also is still not
> really correct: It causes hypercall_xlat_continuation() to be
> bypassed.

Since you've addressed this comment in a subsequent reply, no need to
continue here.

>> @@ -452,6 +454,16 @@ struct xen_mem_access_op {
>>       * ~0ull is used to set and get the default access for pages
>>       */
>>      uint64_aligned_t pfn;
>> +    /*
>> +     * List of pfns to set access for
>> +     * Used only with XENMEM_access_op_set_access_multi
>> +     */
>> +    XEN_GUEST_HANDLE(uint64_t) pfn_list;
> 
> I'm not sure why we even have this kind of handle - please use
> XEN_GUEST_HANDLE(uint64) instead.

I'll change it.

>> +    /*
>> +     * Corresponding list of access settings for pfn_list
>> +     * Used only with XENMEM_access_op_set_access_multi
>> +     */
>> +    XEN_GUEST_HANDLE(uint8) access_list;
> 
> And for both of them - I don't think the arrays are meant to be
> used for output? In which case they should be handles of const
> types.

No, they're indeed not meant for output. I'll constify the code.


Thanks,
Razvan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.