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

[Xen-devel] Re: [PATCH] xen: correctly rebuild mfn list list after migration.



 On 10/12/2010 03:14 AM, Ian Campbell wrote:
> Otherwise the second migration attempt fails because the mfn_list_list
> still refers to all the old mfns.
>
> We need to update the entires in both p2m_top_mfn and the mid_mfn
> pages which p2m_top_mfn refers to.
>
> In order to do this we need to keep track of the virtual addresses
> mapping the p2m_mid_mfn pages since we cannot rely on
> mfn_to_virt(p2m_top_mfn[idx]) since p2m_top_mfn[idx] will still
> contain the old MFN after a migration, which may now belong to another
> domain and hence have a different mapping in the m2p.
>
> Therefore add and maintain a third top level page, p2m_mid_mfn_p[],
> which tracks the virtual addresses of the mfns contained in
> p2m_top_mfn[].
>
> We also need to update the content of the p2m_mid_missing_mfn page on
> resume to refer to the page's new mfn.
>
> p2m_missing does not need updating since the migration process takes
> care of the leaf p2m pages for us.
>
> Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>
> ---
>  arch/x86/xen/mmu.c |   49 ++++++++++++++++++++++++++++++++++++++-----------
>  1 files changed, 38 insertions(+), 11 deletions(-)
>
> diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
> index 16a8e25..8788064 100644
> --- a/arch/x86/xen/mmu.c
> +++ b/arch/x86/xen/mmu.c
> @@ -185,6 +185,8 @@ DEFINE_PER_CPU(unsigned long, xen_current_cr3);    /* 
> actual vcpu cr3 */
>   *    / \      / \         /           /
>   *  p2m p2m p2m p2m p2m p2m p2m ...
>   *
> + * The p2m_mid_mfn pages are mapped by p2m_mid_mfn_p.
> + *
>   * The p2m_top and p2m_top_mfn levels are limited to 1 page, so the
>   * maximum representable pseudo-physical address space is:
>   *  P2M_TOP_PER_PAGE * P2M_MID_PER_PAGE * P2M_PER_PAGE pages
> @@ -209,6 +211,7 @@ static RESERVE_BRK_ARRAY(unsigned long, 
> p2m_mid_missing_mfn, P2M_MID_PER_PAGE);
>  
>  static RESERVE_BRK_ARRAY(unsigned long **, p2m_top, P2M_TOP_PER_PAGE);
>  static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
> +static RESERVE_BRK_ARRAY(unsigned long *, p2m_mid_mfn_p, P2M_TOP_PER_PAGE);
>  
>  RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * 
> P2M_MID_PER_PAGE)));
>  RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * 
> P2M_MID_PER_PAGE)));
> @@ -245,6 +248,14 @@ static void p2m_top_mfn_init(unsigned long *top)
>               top[i] = virt_to_mfn(p2m_mid_missing_mfn);
>  }
>  
> +static void p2m_mid_mfn_p_init(unsigned long **top)
> +{
> +     unsigned i;
> +
> +     for (i = 0; i < P2M_TOP_PER_PAGE; i++)
> +             top[i] = p2m_mid_missing_mfn;
> +}
> +
>  static void p2m_mid_init(unsigned long **mid)
>  {
>       unsigned i;
> @@ -301,15 +312,21 @@ EXPORT_SYMBOL(create_lookup_pte_addr);
>   */
>  void xen_build_mfn_list_list(void)
>  {
> -     unsigned pfn;
> +     unsigned long pfn;
>  
>       /* Pre-initialize p2m_top_mfn to be completely missing */
>       if (p2m_top_mfn == NULL) {
>               p2m_mid_missing_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
>               p2m_mid_mfn_init(p2m_mid_missing_mfn);
>  
> +             p2m_mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
> +             p2m_mid_mfn_p_init(p2m_mid_mfn_p);
> +
>               p2m_top_mfn = extend_brk(PAGE_SIZE, PAGE_SIZE);
>               p2m_top_mfn_init(p2m_top_mfn);
> +     } else {
> +             /* Reinitialise, mfn's all change after migration */
> +             p2m_mid_mfn_init(p2m_mid_missing_mfn);
>       }
>  
>       for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += P2M_PER_PAGE) {
> @@ -322,14 +339,19 @@ void xen_build_mfn_list_list(void)
>               mid = p2m_top[topidx];
>  
>               /* Don't bother allocating any mfn mid levels if
> -                they're just missing */
> -             if (mid[mididx] == p2m_missing)
> +              * they're just missing, just update the stored mfn,
> +              * since all could have changed over a migrate.
> +              */
> +             if (mid == p2m_mid_missing) {
> +                     p2m_top_mfn[topidx] = virt_to_mfn(p2m_mid_missing);
> +                     pfn += P2M_MID_PER_PAGE - 1;
>                       continue;
> +             }
>  
> -             mid_mfn = p2m_top_mfn[topidx];
> -             mid_mfn_p = mfn_to_virt(mid_mfn);
> +             mid_mfn_p = p2m_mid_mfn_p[topidx];
> +             mid_mfn = virt_to_mfn(mid_mfn_p);
>  
> -             if (mid_mfn_p == p2m_mid_missing_mfn) {
> +             if (mid_mfn_p == p2m_missing) {
>                       /*
>                        * XXX boot-time only!  We should never find
>                        * missing parts of the mfn tree after
> @@ -340,10 +362,11 @@ void xen_build_mfn_list_list(void)
>                       p2m_mid_mfn_init(mid_mfn_p);
>  
>                       mid_mfn = virt_to_mfn(mid_mfn_p);
> -                     
> -                     p2m_top_mfn[topidx] = mid_mfn;
> +                     p2m_mid_mfn_p[topidx] = mid_mfn_p;
>               }
>  
> +             p2m_top_mfn[topidx] = mid_mfn;
> +
>               mid_mfn_p[mididx] = virt_to_mfn(mid[mididx]);
>       }
>  }
> @@ -362,7 +385,7 @@ void __init xen_build_dynamic_phys_to_machine(void)
>  {
>       unsigned long *mfn_list = (unsigned long *)xen_start_info->mfn_list;
>       unsigned long max_pfn = min(MAX_DOMAIN_PAGES, xen_start_info->nr_pages);
> -     unsigned pfn;
> +     unsigned long pfn;
>  
>       xen_max_p2m_pfn = max_pfn;
>  
> @@ -452,7 +475,9 @@ static bool alloc_p2m(unsigned long pfn)
>       }
>  
>       top_mfn_p = &p2m_top_mfn[topidx];
> -     mid_mfn = mfn_to_virt(*top_mfn_p);
> +     mid_mfn = p2m_mid_mfn_p[topidx];
> +
> +     BUG_ON(mid_mfn != mfn_to_virt(*top_mfn_p));

I'm getting this triggering at boot:

PM: Adding info for No Bus:xen!gntdev
------------[ cut here ]------------
kernel BUG at /home/jeremy/git/linux/arch/x86/xen/mmu.c:480!
invalid opcode: 0000 [#1] SMP 
last sysfs file: 
CPU 0 
Modules linked in:
Pid: 6, comm: events/0 Not tainted 2.6.32.24-next #220 
RIP: e030:[<ffffffff8100d715>]  [<ffffffff8100d715>] 
set_phys_to_machine+0x12f/0x2d9
RSP: e02b:ffff88001fd8bca0  EFLAGS: 00010206
RAX: ffff88000227d000 RBX: ffffffff8227d000 RCX: 0000000000000016
RDX: ffff880000000000 RSI: 0000000000195a4e RDI: 00000000000207ff
RBP: ffff88001fd8bcf0 R08: 0000000000000003 R09: 00000003981ce0e5
R10: 0000000000000000 R11: 0000000000000003 R12: 00000000000207ff
R13: 0000000000195a4d R14: 0000000000000000 R15: ffffffff8227f000
FS:  0000000000000000(0000) GS:ffff8800051bd000(0000) knlGS:0000000000000000
CS:  e033 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000000 CR3: 0000000001001000 CR4: 0000000000002660
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process events/0 (pid: 6, threadinfo ffff88001fd8a000, task ffff88001fd88180)
Stack:
 2222222222222222 2222222222222222 2222222222222222 ffffffff82278000
<0> 0000000000000001 ffffea0000b2bfa8 00000000000207ff 0000000000000000
<0> 0000000000000200 0000000000000200 ffff88001fd8bdc0 ffffffff812a128e
Call Trace:
 [<ffffffff812a128e>] balloon_process+0x20a/0x626
 [<ffffffff81069cfb>] ? worker_thread+0x1fc/0x347
 [<ffffffff81069d50>] worker_thread+0x251/0x347
 [<ffffffff81069cfb>] ? worker_thread+0x1fc/0x347
 [<ffffffff812a1084>] ? balloon_process+0x0/0x626
 [<ffffffff8106e8ce>] ? autoremove_wake_function+0x0/0x39
 [<ffffffff81069aff>] ? worker_thread+0x0/0x347
 [<ffffffff8106e5f4>] kthread+0x7f/0x87
 [<ffffffff81013e4a>] child_rip+0xa/0x20
 [<ffffffff810137d0>] ? restore_args+0x0/0x30
 [<ffffffff81013e40>] ? child_rip+0x0/0x20
Code: 83 c8 ff eb 10 48 c1 e0 03 31 d2 48 03 05 c4 c3 75 00 48 8b 00 48 c1 e0 
0c 48 ba 00 00 00 00 00 88 ff ff 48 01 d0 48 39 c3 74 04 <0f> 0b eb fe 48 3b 1d 
80 68 94 00 0f 85 bd 00 00 00 31 f6 bf d0 
RIP  [<ffffffff8100d715>] set_phys_to_machine+0x12f/0x2d9
 RSP <ffff88001fd8bca0>
---[ end trace 93d72a36b9146f22 ]---


>  
>       if (mid_mfn == p2m_mid_missing_mfn) {
>               /* Separately check the mid mfn level */
> @@ -464,11 +489,13 @@ static bool alloc_p2m(unsigned long pfn)
>                       return false;
>  
>               p2m_mid_mfn_init(mid_mfn);
> -             
> +
>               missing_mfn = virt_to_mfn(p2m_mid_missing_mfn);
>               mid_mfn_mfn = virt_to_mfn(mid_mfn);
>               if (cmpxchg(top_mfn_p, missing_mfn, mid_mfn_mfn) != missing_mfn)
>                       free_p2m_page(mid_mfn);
> +             else
> +                     p2m_mid_mfn_p[topidx] = mid_mfn;
>       }
>  
>       if (p2m_top[topidx][mididx] == p2m_missing) {


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

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