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

Re: [Xen-devel] [PATCH v2] x86/mm: Add mem access rights to NPT




On 29.08.2019 18:04, Jan Beulich wrote:
> On 22.08.2019 16:02, Alexandru Stefan ISAILA wrote:
>> This patch adds access control for NPT mode.
>>
>> The access rights are stored in the NPT p2m table 56:53.
> 
> Why starting from bit 53? I can't seem to find any use of bit 52.

There is a comment in page.h that warns that bit 12(52) is taken.
"/*
  * Bit 12 of a 24-bit flag mask. This corresponds to bit 52 of a pte.
  * This is needed to distinguish between user and kernel PTEs since 
_PAGE_USER
  * is asserted for both.
  */
#define _PAGE_GUEST_KERNEL (1U<<12)
"

> 
>> The bits are free after clearing the IOMMU flags [1].
>>
>> Modify p2m_type_to_flags() to accept and interpret an access value,
>> parallel to the ept code.
>>
>> Add a set_default_access() method to the p2m-pt and p2m-ept versions
>> of the p2m rather than setting it directly, to deal with different
>> default permitted access values.
> 
> I think this would better be a separate change.

Ok I will brake the patch in two parts. I was following George's v1 patch.

> 
>> --- a/xen/arch/x86/mm/p2m-pt.c
>> +++ b/xen/arch/x86/mm/p2m-pt.c
>> @@ -63,10 +63,13 @@
>>   #define needs_recalc(level, ent) _needs_recalc(level##e_get_flags(ent))
>>   #define valid_recalc(level, ent) (!(level##e_get_flags(ent) & 
>> _PAGE_ACCESSED))
>>   
>> +#define _PAGE_ACCESS_BITS  (0x1e00) /* mem_access rights 16:13 */
> 
> I guess this is too disconnected from the two page.h headers where
> the correlation between bit positions gets explained, so I guess
> you want to extend the comment and either refer there, or replicate
> some of it to make understandable why 16:13 matches 56:53.
> 

I will extend the comment so as the bit shifting will be clear.

> I'm also concerned how easy it'll be for someone to find this
> definition when wanting to use other of the available bits.

Yes you are right, I will add a comment in page.h that bits 56:53 are 
used for memory access rights on SVM.

> 
>> @@ -104,8 +112,32 @@ static unsigned long p2m_type_to_flags(const struct 
>> p2m_domain *p2m,
>>               flags |= _PAGE_PWT;
>>               ASSERT(!level);
>>           }
>> -        return flags | P2M_BASE_FLAGS | _PAGE_PCD;
>> +        flags |= P2M_BASE_FLAGS | _PAGE_PCD;
>> +        break;
>>       }
>> +
>> +    switch ( access )
>> +    {
>> +    case p2m_access_r:
>> +        flags |= _PAGE_NX_BIT;
>> +        flags &= ~_PAGE_RW;
>> +        break;
>> +    case p2m_access_rw:
>> +        flags |= _PAGE_NX_BIT;
>> +        break;
>> +    case p2m_access_rx:
>> +    case p2m_access_rx2rw:
>> +        flags &= ~(_PAGE_NX_BIT | _PAGE_RW);
>> +        break;
>> +    case p2m_access_x:
>> +        flags &= ~_PAGE_RW;
>> +        break;
> 
> I can't seem to be able to follow you here. In fact I don't see
> how you would be able to express execute-only with NPT. If this
> is really needed for some reason, then a justifying comment
> should be added.

Execute-only should be expressed as not PAGE_RW and PAGE_NX_BIT not set.

> 
>> @@ -152,6 +184,17 @@ p2m_free_entry(struct p2m_domain *p2m, l1_pgentry_t 
>> *p2m_entry, int page_order)
>>       p2m_free_ptp(p2m, l1e_get_page(*p2m_entry));
>>   }
>>   
>> +static void p2m_set_access(intpte_t *entry, p2m_access_t access)
>> +{
>> +    *entry |= put_pte_flags((get_pte_flags(*entry) & ~_PAGE_ACCESS_BITS) |
>> +                            (MASK_INSR(access, _PAGE_ACCESS_BITS)));
>> +}
>> +
>> +static p2m_access_t p2m_get_access(intpte_t entry)
>> +{
>> +    return (p2m_access_t)(MASK_EXTR(get_pte_flags(entry), 
>> _PAGE_ACCESS_BITS));
> 
> Is the cast really needed here?

Not really, I can remove it in the next version.

> 
>> @@ -226,6 +269,7 @@ p2m_next_level(struct p2m_domain *p2m, void **table,
>>           {
>>               new_entry = l1e_from_pfn(pfn | (i << ((level - 1) * 
>> PAGETABLE_ORDER)),
>>                                        flags);
>> +            p2m_set_access(&new_entry.l1, p2m->default_access);
>>               rc = p2m->write_p2m_entry(p2m, gfn, l1_entry + i, new_entry, 
>> level);
>>               if ( rc )
>>               {
>> @@ -237,6 +281,7 @@ p2m_next_level(struct p2m_domain *p2m, void **table,
>>           unmap_domain_page(l1_entry);
>>   
>>           new_entry = l1e_from_mfn(mfn, P2M_BASE_FLAGS | _PAGE_RW);
>> +        p2m_set_access(&new_entry.l1, p2m->default_access);
>>           rc = p2m->write_p2m_entry(p2m, gfn, p2m_entry, new_entry,
>>                                     level + 1);
>>           if ( rc )
> 
> Is it really intended to insert the access bits also into non-leaf
> entries (which may be what is being processed here)? (May also
> apply further down.)
> 
>> @@ -474,6 +520,32 @@ int p2m_pt_handle_deferred_changes(uint64_t gpa)
>>       return rc;
>>   }
>>   
>> +static int p2m_pt_check_access(p2m_access_t p2ma)
>> +{
>> +    switch ( p2ma )
>> +    {
>> +    case p2m_access_n:
>> +    case p2m_access_w:
>> +    case p2m_access_wx:
>> +    case p2m_access_n2rwx:
>> +        return -EINVAL;
> 
> I'm not convinced EINVAL is appropriate here - the argument isn't
> invalid, it's just that there's no way to represent it.

Would EPERM be a better return here?

Regards,
Alex
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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