diff mbox

xen/arm: p2m: Don't create new table when the mapping is removed

Message ID 1387387873-3269-1-git-send-email-julien.grall@linaro.org
State Superseded, archived
Headers show

Commit Message

Julien Grall Dec. 18, 2013, 5:31 p.m. UTC
When  Xen is removing/relinquishing mapping, it will create second/third tables
if they don't exist.

Non-existent table means the address range was never mapped, so Xen can safely
skip them.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

---
    Release: This is an improvement for Xen 4.4. It will save time during
    relinquish phase and avoid dummy allocation.
    The downside is the patch is modifying p2m loop which is used everywhere.
---
 xen/arch/arm/p2m.c |   22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

Comments

Stefano Stabellini Dec. 18, 2013, 7:28 p.m. UTC | #1
On Wed, 18 Dec 2013, Julien Grall wrote:
> When  Xen is removing/relinquishing mapping, it will create second/third tables
> if they don't exist.
> 
> Non-existent table means the address range was never mapped, so Xen can safely
> skip them.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> ---
>     Release: This is an improvement for Xen 4.4. It will save time during
>     relinquish phase and avoid dummy allocation.
>     The downside is the patch is modifying p2m loop which is used everywhere.
> ---
>  xen/arch/arm/p2m.c |   22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index d24a6fc..9ef8819 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -246,10 +246,12 @@ static int create_p2m_entries(struct domain *d,
>                    cur_first_offset = ~0,
>                    cur_second_offset = ~0;
>      unsigned long count = 0;
> +    bool_t populate = (op == INSERT || op == ALLOCATE);

why don't you just check for op == REMOVE?


>      spin_lock(&p2m->lock);
>  
> -    for(addr = start_gpaddr; addr < end_gpaddr; addr += PAGE_SIZE)
> +    addr = start_gpaddr;
> +    while ( addr < end_gpaddr )
>      {
>          if ( cur_first_page != p2m_first_level_index(addr) )
>          {
> @@ -265,8 +267,15 @@ static int create_p2m_entries(struct domain *d,
>  
>          if ( !first[first_table_offset(addr)].p2m.valid )
>          {
> +            if ( !populate )
> +            {
> +                addr += FIRST_SIZE;
> +                continue;
> +            }
> +
>              rc = p2m_create_table(d, &first[first_table_offset(addr)]);
> -            if ( rc < 0 ) {
> +            if ( rc < 0 )
> +            {
>                  printk("p2m_populate_ram: L1 failed\n");
>                  goto out;
>              }
> @@ -284,6 +293,12 @@ static int create_p2m_entries(struct domain *d,
>  
>          if ( !second[second_table_offset(addr)].p2m.valid )
>          {
> +            if ( !populate )
> +            {
> +                addr += SECOND_SIZE;
> +                continue;
> +            }
> +
>              rc = p2m_create_table(d, &second[second_table_offset(addr)]);
>              if ( rc < 0 ) {
>                  printk("p2m_populate_ram: L2 failed\n");
> @@ -372,6 +387,9 @@ static int create_p2m_entries(struct domain *d,
>              }
>              count = 0;
>          }
> +
> +        /* Got the next page */
> +        addr += PAGE_SIZE;
>      }
>  
>      if ( op == ALLOCATE || op == INSERT )
> -- 
> 1.7.10.4
>
Julien Grall Dec. 18, 2013, 7:29 p.m. UTC | #2
On 12/18/2013 07:28 PM, Stefano Stabellini wrote:
> On Wed, 18 Dec 2013, Julien Grall wrote:
>> When  Xen is removing/relinquishing mapping, it will create second/third tables
>> if they don't exist.
>>
>> Non-existent table means the address range was never mapped, so Xen can safely
>> skip them.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>>
>> ---
>>      Release: This is an improvement for Xen 4.4. It will save time during
>>      relinquish phase and avoid dummy allocation.
>>      The downside is the patch is modifying p2m loop which is used everywhere.
>> ---
>>   xen/arch/arm/p2m.c |   22 ++++++++++++++++++++--
>>   1 file changed, 20 insertions(+), 2 deletions(-)
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index d24a6fc..9ef8819 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -246,10 +246,12 @@ static int create_p2m_entries(struct domain *d,
>>                     cur_first_offset = ~0,
>>                     cur_second_offset = ~0;
>>       unsigned long count = 0;
>> +    bool_t populate = (op == INSERT || op == ALLOCATE);
>
> why don't you just check for op == REMOVE?

Because you also need to check op == RELINQUISH (added by my patch 
series on foreign mapping).
Stefano Stabellini Dec. 18, 2013, 7:31 p.m. UTC | #3
On Wed, 18 Dec 2013, Julien Grall wrote:
> On 12/18/2013 07:28 PM, Stefano Stabellini wrote:
> > On Wed, 18 Dec 2013, Julien Grall wrote:
> > > When  Xen is removing/relinquishing mapping, it will create second/third
> > > tables
> > > if they don't exist.
> > > 
> > > Non-existent table means the address range was never mapped, so Xen can
> > > safely
> > > skip them.
> > > 
> > > Signed-off-by: Julien Grall <julien.grall@linaro.org>
> > > 
> > > ---
> > >      Release: This is an improvement for Xen 4.4. It will save time during
> > >      relinquish phase and avoid dummy allocation.
> > >      The downside is the patch is modifying p2m loop which is used
> > > everywhere.
> > > ---
> > >   xen/arch/arm/p2m.c |   22 ++++++++++++++++++++--
> > >   1 file changed, 20 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> > > index d24a6fc..9ef8819 100644
> > > --- a/xen/arch/arm/p2m.c
> > > +++ b/xen/arch/arm/p2m.c
> > > @@ -246,10 +246,12 @@ static int create_p2m_entries(struct domain *d,
> > >                     cur_first_offset = ~0,
> > >                     cur_second_offset = ~0;
> > >       unsigned long count = 0;
> > > +    bool_t populate = (op == INSERT || op == ALLOCATE);
> > 
> > why don't you just check for op == REMOVE?
> 
> Because you also need to check op == RELINQUISH (added by my patch series on
> foreign mapping).

I see. In that case

Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Ian Campbell Dec. 19, 2013, 9:38 a.m. UTC | #4
On Wed, 2013-12-18 at 17:31 +0000, Julien Grall wrote:
> When  Xen is removing/relinquishing mapping, it will create second/third tables
> if they don't exist.
> 
> Non-existent table means the address range was never mapped, so Xen can safely
> skip them.
> 
> Signed-off-by: Julien Grall <julien.grall@linaro.org>
> 
> ---
>     Release: This is an improvement for Xen 4.4. It will save time during
>     relinquish phase and avoid dummy allocation.
>     The downside is the patch is modifying p2m loop which is used everywhere.
> ---
>  xen/arch/arm/p2m.c |   22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
> 
> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
> index d24a6fc..9ef8819 100644
> --- a/xen/arch/arm/p2m.c
> +++ b/xen/arch/arm/p2m.c
> @@ -246,10 +246,12 @@ static int create_p2m_entries(struct domain *d,
>                    cur_first_offset = ~0,
>                    cur_second_offset = ~0;
>      unsigned long count = 0;
> +    bool_t populate = (op == INSERT || op == ALLOCATE);
>  
>      spin_lock(&p2m->lock);
>  
> -    for(addr = start_gpaddr; addr < end_gpaddr; addr += PAGE_SIZE)
> +    addr = start_gpaddr;
> +    while ( addr < end_gpaddr )
>      {
>          if ( cur_first_page != p2m_first_level_index(addr) )
>          {
> @@ -265,8 +267,15 @@ static int create_p2m_entries(struct domain *d,
>  
>          if ( !first[first_table_offset(addr)].p2m.valid )
>          {
> +            if ( !populate )
> +            {
> +                addr += FIRST_SIZE;

I think this subtly does the wrong thing if addr is not FIRST_SIZE
aligned, which it might be on the first iteration. That will skip the
start of the next 1st level block.

I think addr needs to be rounded up to the next first boundary.

> +                continue;
> +            }
> +
>              rc = p2m_create_table(d, &first[first_table_offset(addr)]);
> -            if ( rc < 0 ) {
> +            if ( rc < 0 )
> +            {
>                  printk("p2m_populate_ram: L1 failed\n");
>                  goto out;
>              }
> @@ -284,6 +293,12 @@ static int create_p2m_entries(struct domain *d,
>  
>          if ( !second[second_table_offset(addr)].p2m.valid )
>          {
> +            if ( !populate )
> +            {
> +                addr += SECOND_SIZE;

Likewise here.

> +                continue;
> +            }
> +
>              rc = p2m_create_table(d, &second[second_table_offset(addr)]);
>              if ( rc < 0 ) {
>                  printk("p2m_populate_ram: L2 failed\n");
> @@ -372,6 +387,9 @@ static int create_p2m_entries(struct domain *d,
>              }
>              count = 0;
>          }
> +
> +        /* Got the next page */
> +        addr += PAGE_SIZE;
>      }
>  
>      if ( op == ALLOCATE || op == INSERT )
Julien Grall Dec. 19, 2013, 3:28 p.m. UTC | #5
On 12/19/2013 09:38 AM, Ian Campbell wrote:
> On Wed, 2013-12-18 at 17:31 +0000, Julien Grall wrote:
>> When  Xen is removing/relinquishing mapping, it will create second/third tables
>> if they don't exist.
>>
>> Non-existent table means the address range was never mapped, so Xen can safely
>> skip them.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>>
>> ---
>>     Release: This is an improvement for Xen 4.4. It will save time during
>>     relinquish phase and avoid dummy allocation.
>>     The downside is the patch is modifying p2m loop which is used everywhere.
>> ---
>>  xen/arch/arm/p2m.c |   22 ++++++++++++++++++++--
>>  1 file changed, 20 insertions(+), 2 deletions(-)
>>
>> diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
>> index d24a6fc..9ef8819 100644
>> --- a/xen/arch/arm/p2m.c
>> +++ b/xen/arch/arm/p2m.c
>> @@ -246,10 +246,12 @@ static int create_p2m_entries(struct domain *d,
>>                    cur_first_offset = ~0,
>>                    cur_second_offset = ~0;
>>      unsigned long count = 0;
>> +    bool_t populate = (op == INSERT || op == ALLOCATE);
>>  
>>      spin_lock(&p2m->lock);
>>  
>> -    for(addr = start_gpaddr; addr < end_gpaddr; addr += PAGE_SIZE)
>> +    addr = start_gpaddr;
>> +    while ( addr < end_gpaddr )
>>      {
>>          if ( cur_first_page != p2m_first_level_index(addr) )
>>          {
>> @@ -265,8 +267,15 @@ static int create_p2m_entries(struct domain *d,
>>  
>>          if ( !first[first_table_offset(addr)].p2m.valid )
>>          {
>> +            if ( !populate )
>> +            {
>> +                addr += FIRST_SIZE;
> 
> I think this subtly does the wrong thing if addr is not FIRST_SIZE
> aligned, which it might be on the first iteration. That will skip the
> start of the next 1st level block.
> 
> I think addr needs to be rounded up to the next first boundary.

Right, I will send a new version of this patch.
diff mbox

Patch

diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index d24a6fc..9ef8819 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -246,10 +246,12 @@  static int create_p2m_entries(struct domain *d,
                   cur_first_offset = ~0,
                   cur_second_offset = ~0;
     unsigned long count = 0;
+    bool_t populate = (op == INSERT || op == ALLOCATE);
 
     spin_lock(&p2m->lock);
 
-    for(addr = start_gpaddr; addr < end_gpaddr; addr += PAGE_SIZE)
+    addr = start_gpaddr;
+    while ( addr < end_gpaddr )
     {
         if ( cur_first_page != p2m_first_level_index(addr) )
         {
@@ -265,8 +267,15 @@  static int create_p2m_entries(struct domain *d,
 
         if ( !first[first_table_offset(addr)].p2m.valid )
         {
+            if ( !populate )
+            {
+                addr += FIRST_SIZE;
+                continue;
+            }
+
             rc = p2m_create_table(d, &first[first_table_offset(addr)]);
-            if ( rc < 0 ) {
+            if ( rc < 0 )
+            {
                 printk("p2m_populate_ram: L1 failed\n");
                 goto out;
             }
@@ -284,6 +293,12 @@  static int create_p2m_entries(struct domain *d,
 
         if ( !second[second_table_offset(addr)].p2m.valid )
         {
+            if ( !populate )
+            {
+                addr += SECOND_SIZE;
+                continue;
+            }
+
             rc = p2m_create_table(d, &second[second_table_offset(addr)]);
             if ( rc < 0 ) {
                 printk("p2m_populate_ram: L2 failed\n");
@@ -372,6 +387,9 @@  static int create_p2m_entries(struct domain *d,
             }
             count = 0;
         }
+
+        /* Got the next page */
+        addr += PAGE_SIZE;
     }
 
     if ( op == ALLOCATE || op == INSERT )