diff mbox

[13/18] arm/altp2m: Make get_page_from_gva ready for altp2m.

Message ID 20160704114605.10086-14-proskurin@sec.in.tum.de (mailing list archive)
State New, archived
Headers show

Commit Message

Sergej Proskurin July 4, 2016, 11:45 a.m. UTC
This commit adapts get_page_from_gva to consider the currently mapped
altp2m view during address translation. We also adapt the function's
prototype (provide "struct vcpu *" instead of "struct domain *"). This
change is required, as the function indirectly calls the function
gva_to_ma_par, which requires the mmu to use the current p2m mapping. So
if the caller is interested in a page that must be claimed from a vCPU
other than current, it must temporarily set the altp2m view that is used
by the vCPU in question.  Therefore, we need to provide the particular
vCPU to this function.

Signed-off-by: Sergej Proskurin <proskurin@sec.in.tum.de>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
---
 xen/arch/arm/guestcopy.c |  6 +++---
 xen/arch/arm/p2m.c       | 19 +++++++++++++------
 xen/arch/arm/traps.c     |  2 +-
 xen/include/asm-arm/mm.h |  2 +-
 4 files changed, 18 insertions(+), 11 deletions(-)

Comments

Julien Grall July 4, 2016, 8:34 p.m. UTC | #1
Hello Sergej,

On 04/07/2016 12:45, Sergej Proskurin wrote:
> diff --git a/xen/arch/arm/guestcopy.c b/xen/arch/arm/guestcopy.c
> index ce1c3c3..413125f 100644
> --- a/xen/arch/arm/guestcopy.c
> +++ b/xen/arch/arm/guestcopy.c
> @@ -17,7 +17,7 @@ static unsigned long raw_copy_to_guest_helper(void *to, const void *from,
>          unsigned size = min(len, (unsigned)PAGE_SIZE - offset);
>          struct page_info *page;
>
> -        page = get_page_from_gva(current->domain, (vaddr_t) to, GV2M_WRITE);
> +        page = get_page_from_gva(current, (vaddr_t) to, GV2M_WRITE);
>          if ( page == NULL )
>              return len;
>
> @@ -64,7 +64,7 @@ unsigned long raw_clear_guest(void *to, unsigned len)
>          unsigned size = min(len, (unsigned)PAGE_SIZE - offset);
>          struct page_info *page;
>
> -        page = get_page_from_gva(current->domain, (vaddr_t) to, GV2M_WRITE);
> +        page = get_page_from_gva(current, (vaddr_t) to, GV2M_WRITE);
>          if ( page == NULL )
>              return len;
>
> @@ -96,7 +96,7 @@ unsigned long raw_copy_from_guest(void *to, const void __user *from, unsigned le
>          unsigned size = min(len, (unsigned)(PAGE_SIZE - offset));
>          struct page_info *page;
>
> -        page = get_page_from_gva(current->domain, (vaddr_t) from, GV2M_READ);
> +        page = get_page_from_gva(current, (vaddr_t) from, GV2M_READ);
>          if ( page == NULL )
>              return len;
>
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index 9c8fefd..23b482f 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -1829,10 +1829,11 @@ err:
>      return page;
>  }
>
> -struct page_info *get_page_from_gva(struct domain *d, vaddr_t va,
> +struct page_info *get_page_from_gva(struct vcpu *v, vaddr_t va,
>                                      unsigned long flags)
>  {
> -    struct p2m_domain *p2m = &d->arch.p2m;
> +    struct domain *d = v->domain;
> +    struct p2m_domain *p2m = altp2m_active(d) ? p2m_get_altp2m(v) : p2m_get_hostp2m(d);
>      struct page_info *page = NULL;
>      paddr_t maddr = 0;
>      int rc;
> @@ -1844,17 +1845,23 @@ struct page_info *get_page_from_gva(struct domain *d, vaddr_t va,
>          unsigned long irq_flags;
>
>          local_irq_save(irq_flags);
> -        p2m_load_VTTBR(d);
> +
> +        if ( altp2m_active(d) )
> +            p2m_load_altp2m_VTTBR(v);
> +        else
> +            p2m_load_VTTBR(d);
>
>          rc = gvirt_to_maddr(va, &maddr, flags);
>
> -        p2m_load_VTTBR(current->domain);
> +        if ( altp2m_active(current->domain) )
> +            p2m_load_altp2m_VTTBR(current);
> +        else
> +            p2m_load_VTTBR(current->domain);
> +

This could be abstracted with a new helper to load the VTTBR for a given 
vCPU.

>          local_irq_restore(irq_flags);
>      }
>      else
> -    {
>          rc = gvirt_to_maddr(va, &maddr, flags);
> -    }
>
>      if ( rc )
>          goto err;

Regards,
Sergej Proskurin July 5, 2016, 8:31 p.m. UTC | #2
Hi Julien,

On 07/04/2016 10:34 PM, Julien Grall wrote:
> Hello Sergej,
> 
> On 04/07/2016 12:45, Sergej Proskurin wrote:
>> diff --git a/xen/arch/arm/guestcopy.c b/xen/arch/arm/guestcopy.c
>> index ce1c3c3..413125f 100644
>> --- a/xen/arch/arm/guestcopy.c
>> +++ b/xen/arch/arm/guestcopy.c
>> @@ -17,7 +17,7 @@ static unsigned long raw_copy_to_guest_helper(void
>> *to, const void *from,
>>          unsigned size = min(len, (unsigned)PAGE_SIZE - offset);
>>          struct page_info *page;
>>
>> -        page = get_page_from_gva(current->domain, (vaddr_t) to,
>> GV2M_WRITE);
>> +        page = get_page_from_gva(current, (vaddr_t) to, GV2M_WRITE);
>>          if ( page == NULL )
>>              return len;
>>
>> @@ -64,7 +64,7 @@ unsigned long raw_clear_guest(void *to, unsigned len)
>>          unsigned size = min(len, (unsigned)PAGE_SIZE - offset);
>>          struct page_info *page;
>>
>> -        page = get_page_from_gva(current->domain, (vaddr_t) to,
>> GV2M_WRITE);
>> +        page = get_page_from_gva(current, (vaddr_t) to, GV2M_WRITE);
>>          if ( page == NULL )
>>              return len;
>>
>> @@ -96,7 +96,7 @@ unsigned long raw_copy_from_guest(void *to, const
>> void __user *from, unsigned le
>>          unsigned size = min(len, (unsigned)(PAGE_SIZE - offset));
>>          struct page_info *page;
>>
>> -        page = get_page_from_gva(current->domain, (vaddr_t) from,
>> GV2M_READ);
>> +        page = get_page_from_gva(current, (vaddr_t) from, GV2M_READ);
>>          if ( page == NULL )
>>              return len;
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index 9c8fefd..23b482f 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -1829,10 +1829,11 @@ err:
>>      return page;
>>  }
>>
>> -struct page_info *get_page_from_gva(struct domain *d, vaddr_t va,
>> +struct page_info *get_page_from_gva(struct vcpu *v, vaddr_t va,
>>                                      unsigned long flags)
>>  {
>> -    struct p2m_domain *p2m = &d->arch.p2m;
>> +    struct domain *d = v->domain;
>> +    struct p2m_domain *p2m = altp2m_active(d) ? p2m_get_altp2m(v) :
>> p2m_get_hostp2m(d);
>>      struct page_info *page = NULL;
>>      paddr_t maddr = 0;
>>      int rc;
>> @@ -1844,17 +1845,23 @@ struct page_info *get_page_from_gva(struct
>> domain *d, vaddr_t va,
>>          unsigned long irq_flags;
>>
>>          local_irq_save(irq_flags);
>> -        p2m_load_VTTBR(d);
>> +
>> +        if ( altp2m_active(d) )
>> +            p2m_load_altp2m_VTTBR(v);
>> +        else
>> +            p2m_load_VTTBR(d);
>>
>>          rc = gvirt_to_maddr(va, &maddr, flags);
>>
>> -        p2m_load_VTTBR(current->domain);
>> +        if ( altp2m_active(current->domain) )
>> +            p2m_load_altp2m_VTTBR(current);
>> +        else
>> +            p2m_load_VTTBR(current->domain);
>> +
> 
> This could be abstracted with a new helper to load the VTTBR for a given
> vCPU.
> 

For my next patch series, I will think about an abstraction of the
function p2m_load[_altp2m]_VTTBR or a merge of both functions into one,
as discussed in path #11. Thank you.

>>          local_irq_restore(irq_flags);
>>      }
>>      else
>> -    {
>>          rc = gvirt_to_maddr(va, &maddr, flags);
>> -    }
>>
>>      if ( rc )
>>          goto err;
> 
> Regards,
> 

Cheers,
~Sergej
diff mbox

Patch

diff --git a/xen/arch/arm/guestcopy.c b/xen/arch/arm/guestcopy.c
index ce1c3c3..413125f 100644
--- a/xen/arch/arm/guestcopy.c
+++ b/xen/arch/arm/guestcopy.c
@@ -17,7 +17,7 @@  static unsigned long raw_copy_to_guest_helper(void *to, const void *from,
         unsigned size = min(len, (unsigned)PAGE_SIZE - offset);
         struct page_info *page;
 
-        page = get_page_from_gva(current->domain, (vaddr_t) to, GV2M_WRITE);
+        page = get_page_from_gva(current, (vaddr_t) to, GV2M_WRITE);
         if ( page == NULL )
             return len;
 
@@ -64,7 +64,7 @@  unsigned long raw_clear_guest(void *to, unsigned len)
         unsigned size = min(len, (unsigned)PAGE_SIZE - offset);
         struct page_info *page;
 
-        page = get_page_from_gva(current->domain, (vaddr_t) to, GV2M_WRITE);
+        page = get_page_from_gva(current, (vaddr_t) to, GV2M_WRITE);
         if ( page == NULL )
             return len;
 
@@ -96,7 +96,7 @@  unsigned long raw_copy_from_guest(void *to, const void __user *from, unsigned le
         unsigned size = min(len, (unsigned)(PAGE_SIZE - offset));
         struct page_info *page;
 
-        page = get_page_from_gva(current->domain, (vaddr_t) from, GV2M_READ);
+        page = get_page_from_gva(current, (vaddr_t) from, GV2M_READ);
         if ( page == NULL )
             return len;
 
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 9c8fefd..23b482f 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -1829,10 +1829,11 @@  err:
     return page;
 }
 
-struct page_info *get_page_from_gva(struct domain *d, vaddr_t va,
+struct page_info *get_page_from_gva(struct vcpu *v, vaddr_t va,
                                     unsigned long flags)
 {
-    struct p2m_domain *p2m = &d->arch.p2m;
+    struct domain *d = v->domain;
+    struct p2m_domain *p2m = altp2m_active(d) ? p2m_get_altp2m(v) : p2m_get_hostp2m(d);
     struct page_info *page = NULL;
     paddr_t maddr = 0;
     int rc;
@@ -1844,17 +1845,23 @@  struct page_info *get_page_from_gva(struct domain *d, vaddr_t va,
         unsigned long irq_flags;
 
         local_irq_save(irq_flags);
-        p2m_load_VTTBR(d);
+
+        if ( altp2m_active(d) )
+            p2m_load_altp2m_VTTBR(v);
+        else
+            p2m_load_VTTBR(d);
 
         rc = gvirt_to_maddr(va, &maddr, flags);
 
-        p2m_load_VTTBR(current->domain);
+        if ( altp2m_active(current->domain) )
+            p2m_load_altp2m_VTTBR(current);
+        else
+            p2m_load_VTTBR(current->domain);
+
         local_irq_restore(irq_flags);
     }
     else
-    {
         rc = gvirt_to_maddr(va, &maddr, flags);
-    }
 
     if ( rc )
         goto err;
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 44926ca..6995971 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -957,7 +957,7 @@  static void show_guest_stack(struct vcpu *v, struct cpu_user_regs *regs)
         return;
     }
 
-    page = get_page_from_gva(v->domain, sp, GV2M_READ);
+    page = get_page_from_gva(v, sp, GV2M_READ);
     if ( page == NULL )
     {
         printk("Failed to convert stack to physical address\n");
diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h
index 68cf203..19eadd2 100644
--- a/xen/include/asm-arm/mm.h
+++ b/xen/include/asm-arm/mm.h
@@ -281,7 +281,7 @@  static inline void *page_to_virt(const struct page_info *pg)
     return mfn_to_virt(page_to_mfn(pg));
 }
 
-struct page_info *get_page_from_gva(struct domain *d, vaddr_t va,
+struct page_info *get_page_from_gva(struct vcpu *v, vaddr_t va,
                                     unsigned long flags);
 
 /*