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
|