Re: [Xen-devel] [PATCH 07/12] x86/virt/guest/xen: Remove use of pgd_list from the Xen guest code

2015-06-16 Thread David Vrabel
On 16/06/15 15:19, Boris Ostrovsky wrote:
> On 06/16/2015 10:15 AM, David Vrabel wrote:
>> On 15/06/15 21:35, Ingo Molnar wrote:
>>> * David Vrabel  wrote:
>>>
 On 15/06/15 10:05, Ian Campbell wrote:
> On Sat, 2015-06-13 at 11:49 +0200, Ingo Molnar wrote:
>> xen_mm_pin_all()/unpin_all() are used to implement full guest
>> instance
>> suspend/restore. It's a stop-all method that needs to iterate
>> through all
>> allocated pgds in the system to fix them up for Xen's use.
>>
>> This code uses pgd_list, probably because it was an easy interface.
>>
>> But we want to remove the pgd_list, so convert the code over to
>> walk all
>> tasks in the system. This is an equivalent method.
 It is not equivalent because pgd_alloc() now populates entries in
 pgds that are
 not visible to xen_mm_pin_all() (note how the original code adds the
 pgd to the
 pgd_list in pgd_ctor() before calling pgd_prepopulate_pmd()).  These
 newly
 allocated page tables won't be correctly converted on suspend/resume
 and the new
 process will die after resume.
>>> So how should the Xen logic be fixed for the new scheme? I can't say
>>> I can see
>>> through the paravirt complexity here.
>> Actually, since we freeze_processes() before trying to pin page tables,
>> I think it should be ok as-is.
>>
>> I'll put the patch through some tests.
> 
> Actually, I just ran this through a couple of boot/suspend/resume tests
> and didn't see any issues (with the one fix I mentioned to Ingo
> earlier). On unstable Xen only.

In which case this can have a:

Reviewed-by: David Vrabel 

Thanks.

David

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 07/12] x86/virt/guest/xen: Remove use of pgd_list from the Xen guest code

2015-06-16 Thread Boris Ostrovsky

On 06/16/2015 10:15 AM, David Vrabel wrote:

On 15/06/15 21:35, Ingo Molnar wrote:

* David Vrabel  wrote:


On 15/06/15 10:05, Ian Campbell wrote:

On Sat, 2015-06-13 at 11:49 +0200, Ingo Molnar wrote:

xen_mm_pin_all()/unpin_all() are used to implement full guest instance
suspend/restore. It's a stop-all method that needs to iterate through all
allocated pgds in the system to fix them up for Xen's use.

This code uses pgd_list, probably because it was an easy interface.

But we want to remove the pgd_list, so convert the code over to walk all
tasks in the system. This is an equivalent method.

It is not equivalent because pgd_alloc() now populates entries in pgds that are
not visible to xen_mm_pin_all() (note how the original code adds the pgd to the
pgd_list in pgd_ctor() before calling pgd_prepopulate_pmd()).  These newly
allocated page tables won't be correctly converted on suspend/resume and the new
process will die after resume.

So how should the Xen logic be fixed for the new scheme? I can't say I can see
through the paravirt complexity here.

Actually, since we freeze_processes() before trying to pin page tables,
I think it should be ok as-is.

I'll put the patch through some tests.


Actually, I just ran this through a couple of boot/suspend/resume tests 
and didn't see any issues (with the one fix I mentioned to Ingo 
earlier). On unstable Xen only.


-boris



___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 07/12] x86/virt/guest/xen: Remove use of pgd_list from the Xen guest code

2015-06-16 Thread David Vrabel
On 15/06/15 21:35, Ingo Molnar wrote:
> 
> * David Vrabel  wrote:
> 
>> On 15/06/15 10:05, Ian Campbell wrote:
>>> On Sat, 2015-06-13 at 11:49 +0200, Ingo Molnar wrote:
> 
 xen_mm_pin_all()/unpin_all() are used to implement full guest instance 
 suspend/restore. It's a stop-all method that needs to iterate through all 
 allocated pgds in the system to fix them up for Xen's use.

 This code uses pgd_list, probably because it was an easy interface.

 But we want to remove the pgd_list, so convert the code over to walk all 
 tasks in the system. This is an equivalent method.
>>
>> It is not equivalent because pgd_alloc() now populates entries in pgds that 
>> are 
>> not visible to xen_mm_pin_all() (note how the original code adds the pgd to 
>> the 
>> pgd_list in pgd_ctor() before calling pgd_prepopulate_pmd()).  These newly 
>> allocated page tables won't be correctly converted on suspend/resume and the 
>> new 
>> process will die after resume.
> 
> So how should the Xen logic be fixed for the new scheme? I can't say I can 
> see 
> through the paravirt complexity here.

Actually, since we freeze_processes() before trying to pin page tables,
I think it should be ok as-is.

I'll put the patch through some tests.

David

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 07/12] x86/virt/guest/xen: Remove use of pgd_list from the Xen guest code

2015-06-15 Thread Ingo Molnar

* David Vrabel  wrote:

> On 15/06/15 10:05, Ian Campbell wrote:
> > On Sat, 2015-06-13 at 11:49 +0200, Ingo Molnar wrote:

> >> xen_mm_pin_all()/unpin_all() are used to implement full guest instance 
> >> suspend/restore. It's a stop-all method that needs to iterate through all 
> >> allocated pgds in the system to fix them up for Xen's use.
> >>
> >> This code uses pgd_list, probably because it was an easy interface.
> >>
> >> But we want to remove the pgd_list, so convert the code over to walk all 
> >> tasks in the system. This is an equivalent method.
> 
> It is not equivalent because pgd_alloc() now populates entries in pgds that 
> are 
> not visible to xen_mm_pin_all() (note how the original code adds the pgd to 
> the 
> pgd_list in pgd_ctor() before calling pgd_prepopulate_pmd()).  These newly 
> allocated page tables won't be correctly converted on suspend/resume and the 
> new 
> process will die after resume.

So how should the Xen logic be fixed for the new scheme? I can't say I can see 
through the paravirt complexity here.

Thanks,

Ingo

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 07/12] x86/virt/guest/xen: Remove use of pgd_list from the Xen guest code

2015-06-15 Thread David Vrabel
On 15/06/15 10:05, Ian Campbell wrote:
> On Sat, 2015-06-13 at 11:49 +0200, Ingo Molnar wrote:
>> xen_mm_pin_all()/unpin_all() are used to implement full guest instance
>> suspend/restore. It's a stop-all method that needs to iterate through
>> all allocated pgds in the system to fix them up for Xen's use.
>>
>> This code uses pgd_list, probably because it was an easy interface.
>>
>> But we want to remove the pgd_list, so convert the code over to walk
>> all tasks in the system. This is an equivalent method.

It is not equivalent because pgd_alloc() now populates entries in pgds
that are not visible to xen_mm_pin_all() (note how the original code
adds the pgd to the pgd_list in pgd_ctor() before calling
pgd_prepopulate_pmd()).  These newly allocated page tables won't be
correctly converted on suspend/resume and the new process will die after
resume.

David

>>
>> (As I don't use Xen this is was only build tested.)
> 
> In which case it seems extra important to copy the appropriate
> maintainers, which I've done here.
> 
> Ian.
> 
>>
>> Cc: Andrew Morton 
>> Cc: Andy Lutomirski 
>> Cc: Borislav Petkov 
>> Cc: Brian Gerst 
>> Cc: Denys Vlasenko 
>> Cc: H. Peter Anvin 
>> Cc: Linus Torvalds 
>> Cc: Oleg Nesterov 
>> Cc: Peter Zijlstra 
>> Cc: Thomas Gleixner 
>> Cc: Waiman Long 
>> Cc: linux...@kvack.org
>> Signed-off-by: Ingo Molnar 
>> ---
>>  arch/x86/xen/mmu.c | 51 ++-
>>  1 file changed, 38 insertions(+), 13 deletions(-)
>>
>> diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
>> index dd151b2045b0..70a3df5b0b54 100644
>> --- a/arch/x86/xen/mmu.c
>> +++ b/arch/x86/xen/mmu.c
>> @@ -853,15 +853,27 @@ static void xen_pgd_pin(struct mm_struct *mm)
>>   */
>>  void xen_mm_pin_all(void)
>>  {
>> -struct page *page;
>> +struct task_struct *g, *p;
>>  
>> -spin_lock(&pgd_lock);
>> +spin_lock(&pgd_lock); /* Implies rcu_read_lock() for the task list 
>> iteration: */
>>  
>> -list_for_each_entry(page, &pgd_list, lru) {
>> -if (!PagePinned(page)) {
>> -__xen_pgd_pin(&init_mm, (pgd_t *)page_address(page));
>> -SetPageSavePinned(page);
>> +for_each_process_thread(g, p) {
>> +struct mm_struct *mm;
>> +struct page *page;
>> +pgd_t *pgd;
>> +
>> +task_lock(p);
>> +mm = p->mm;
>> +if (mm) {
>> +pgd = mm->pgd;
>> +page = virt_to_page(pgd);
>> +
>> +if (!PagePinned(page)) {
>> +__xen_pgd_pin(&init_mm, pgd);
>> +SetPageSavePinned(page);
>> +}
>>  }
>> +task_unlock(p);
>>  }
>>  
>>  spin_unlock(&pgd_lock);
>> @@ -967,19 +979,32 @@ static void xen_pgd_unpin(struct mm_struct *mm)
>>   */
>>  void xen_mm_unpin_all(void)
>>  {
>> -struct page *page;
>> +struct task_struct *g, *p;
>>  
>> -spin_lock(&pgd_lock);
>> +spin_lock(&pgd_lock); /* Implies rcu_read_lock() for the task list 
>> iteration: */
>>  
>> -list_for_each_entry(page, &pgd_list, lru) {
>> -if (PageSavePinned(page)) {
>> -BUG_ON(!PagePinned(page));
>> -__xen_pgd_unpin(&init_mm, (pgd_t *)page_address(page));
>> -ClearPageSavePinned(page);
>> +for_each_process_thread(g, p) {
>> +struct mm_struct *mm;
>> +struct page *page;
>> +pgd_t *pgd;
>> +
>> +task_lock(p);
>> +mm = p->mm;
>> +if (mm) {
>> +pgd = mm->pgd;
>> +page = virt_to_page(pgd);
>> +
>> +if (PageSavePinned(page)) {
>> +BUG_ON(!PagePinned(page));
>> +__xen_pgd_unpin(&init_mm, pgd);
>> +ClearPageSavePinned(page);
>> +}
>>  }
>> +task_unlock(p);
>>  }
>>  
>>  spin_unlock(&pgd_lock);
>> +rcu_read_unlock();
>>  }
>>  
>>  static void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next)
> 
> 


___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [PATCH 07/12] x86/virt/guest/xen: Remove use of pgd_list from the Xen guest code

2015-06-15 Thread Ian Campbell
On Sat, 2015-06-13 at 11:49 +0200, Ingo Molnar wrote:
> xen_mm_pin_all()/unpin_all() are used to implement full guest instance
> suspend/restore. It's a stop-all method that needs to iterate through
> all allocated pgds in the system to fix them up for Xen's use.
> 
> This code uses pgd_list, probably because it was an easy interface.
> 
> But we want to remove the pgd_list, so convert the code over to walk
> all tasks in the system. This is an equivalent method.
> 
> (As I don't use Xen this is was only build tested.)

In which case it seems extra important to copy the appropriate
maintainers, which I've done here.

Ian.

> 
> Cc: Andrew Morton 
> Cc: Andy Lutomirski 
> Cc: Borislav Petkov 
> Cc: Brian Gerst 
> Cc: Denys Vlasenko 
> Cc: H. Peter Anvin 
> Cc: Linus Torvalds 
> Cc: Oleg Nesterov 
> Cc: Peter Zijlstra 
> Cc: Thomas Gleixner 
> Cc: Waiman Long 
> Cc: linux...@kvack.org
> Signed-off-by: Ingo Molnar 
> ---
>  arch/x86/xen/mmu.c | 51 ++-
>  1 file changed, 38 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
> index dd151b2045b0..70a3df5b0b54 100644
> --- a/arch/x86/xen/mmu.c
> +++ b/arch/x86/xen/mmu.c
> @@ -853,15 +853,27 @@ static void xen_pgd_pin(struct mm_struct *mm)
>   */
>  void xen_mm_pin_all(void)
>  {
> - struct page *page;
> + struct task_struct *g, *p;
>  
> - spin_lock(&pgd_lock);
> + spin_lock(&pgd_lock); /* Implies rcu_read_lock() for the task list 
> iteration: */
>  
> - list_for_each_entry(page, &pgd_list, lru) {
> - if (!PagePinned(page)) {
> - __xen_pgd_pin(&init_mm, (pgd_t *)page_address(page));
> - SetPageSavePinned(page);
> + for_each_process_thread(g, p) {
> + struct mm_struct *mm;
> + struct page *page;
> + pgd_t *pgd;
> +
> + task_lock(p);
> + mm = p->mm;
> + if (mm) {
> + pgd = mm->pgd;
> + page = virt_to_page(pgd);
> +
> + if (!PagePinned(page)) {
> + __xen_pgd_pin(&init_mm, pgd);
> + SetPageSavePinned(page);
> + }
>   }
> + task_unlock(p);
>   }
>  
>   spin_unlock(&pgd_lock);
> @@ -967,19 +979,32 @@ static void xen_pgd_unpin(struct mm_struct *mm)
>   */
>  void xen_mm_unpin_all(void)
>  {
> - struct page *page;
> + struct task_struct *g, *p;
>  
> - spin_lock(&pgd_lock);
> + spin_lock(&pgd_lock); /* Implies rcu_read_lock() for the task list 
> iteration: */
>  
> - list_for_each_entry(page, &pgd_list, lru) {
> - if (PageSavePinned(page)) {
> - BUG_ON(!PagePinned(page));
> - __xen_pgd_unpin(&init_mm, (pgd_t *)page_address(page));
> - ClearPageSavePinned(page);
> + for_each_process_thread(g, p) {
> + struct mm_struct *mm;
> + struct page *page;
> + pgd_t *pgd;
> +
> + task_lock(p);
> + mm = p->mm;
> + if (mm) {
> + pgd = mm->pgd;
> + page = virt_to_page(pgd);
> +
> + if (PageSavePinned(page)) {
> + BUG_ON(!PagePinned(page));
> + __xen_pgd_unpin(&init_mm, pgd);
> + ClearPageSavePinned(page);
> + }
>   }
> + task_unlock(p);
>   }
>  
>   spin_unlock(&pgd_lock);
> + rcu_read_unlock();
>  }
>  
>  static void xen_activate_mm(struct mm_struct *prev, struct mm_struct *next)



___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel