On Mon, 2020-01-20 at 17:58 +0100, Jan Beulich wrote: > On 08.01.2020 18:24, David Woodhouse wrote: > > @@ -980,6 +1015,22 @@ void __init noreturn __start_xen(unsigned long mbi_p) > > set_kexec_crash_area_size((u64)nr_pages << PAGE_SHIFT); > > kexec_reserve_area(&boot_e820); > > > > + if ( lu_bootmem_start ) > > + { > > + /* XX: Check it's in usable memory first */ > > + reserve_e820_ram(&boot_e820, lu_bootmem_start, lu_bootmem_start + lu_bootmem_size); > > + > > + /* Since it will already be out of the e820 map by the time the first > > + * loop over physical memory, map it manually already. */ > > + set_pdx_range(lu_bootmem_start >> PAGE_SHIFT, > > + (lu_bootmem_start + lu_bootmem_size) >> PAGE_SHIFT); > > + map_pages_to_xen((unsigned long)__va(lu_bootmem_start), > > + maddr_to_mfn(lu_bootmem_start), > > + PFN_DOWN(lu_bootmem_size), PAGE_HYPERVISOR); > > Doesn't this require the range to be a multiple of 2Mb and below > 4Gb? I don't see this enforced anywhere. Aha, so *that's* why the mapping succeeded without having to allocate any memory for PTEs. That did confuse me for a while, before I figured my time was better spent in the short term by focusing on things I don't understand that *weren't* working, rather than things I didn't understand that *were*. :) Yes, if this is the solution we end up with (and I do think it's still the best option I've seen), then the requirement should be clearly documented and enforced. Andy and Hongyan are busy messing with all the 1:1 mappings, both at boot time and at run time, so the actual restrictions may change. > > @@ -1278,8 +1348,8 @@ void __init noreturn __start_xen(unsigned long mbi_p) > > xenheap_max_mfn(PFN_DOWN(highmem_start - 1)); > > > > /* > > - * Walk every RAM region and map it in its entirety (on x86/64, at least) > > - * and notify it to the boot allocator. > > + * Walk every RAM region and map it in its entirety and (unless in > > + * live update mode) notify it to the boot allocator. > > */ > > for ( i = 0; i < boot_e820.nr_map; i++ ) > > { > > @@ -1329,6 +1399,7 @@ void __init noreturn __start_xen(unsigned long mbi_p) > > printk(XENLOG_WARNING "Ignoring inaccessible memory range" > > " %013"PRIx64"-%013"PRIx64"\n", > > s, e); > > + reserve_e820_ram(&boot_e820, s, e); > > continue; > > } > > map_e = e; > > @@ -1336,6 +1407,7 @@ void __init noreturn __start_xen(unsigned long mbi_p) > > printk(XENLOG_WARNING "Ignoring inaccessible memory range" > > " %013"PRIx64"-%013"PRIx64"\n", > > e, map_e); > > + reserve_e820_ram(&boot_e820, e, map_e); > > } > > > > set_pdx_range(s >> PAGE_SHIFT, e >> PAGE_SHIFT); > > What are these two hunks needed for? The comment you change further up > relates to ... When we use only the LU-reserved region for bootmem, we defer the registration of the other regions found in E820 to a later pass, after we've consumed the live update state (and know which pages not to touch). So instead of just ignoring those inaccessible regions in the first loop as we did before, we need to *mark* them reserved in our E820 data so that they don't get registered by that second pass. > > @@ -1346,7 +1418,9 @@ void __init noreturn __start_xen(unsigned long mbi_p) > > ARRAY_SIZE(l2_identmap) << L2_PAGETABLE_SHIFT); > > > > /* Pass mapped memory to allocator /before/ creating new mappings. */ > > - init_boot_pages(s, min(map_s, e)); > > + if ( !lu_reserved) > > + init_boot_pages(s, min(map_s, e)); > > ... this afaict. Kind of, but more to the point applicable to where we later *do* register those pages, around line 1600. > Apart from this, also applicable to patch 3 - where I have no other > comments - there's quite a bit of style cleanup to b done here. And > of course the new command line option wants documenting. I can't > e.g. guess yet what lu_data is about, and hence why this is > apparently an address without an accompanying size. Right. The lu_data is intended to be the 'breadcrumb' which leads to the actual live update state, which is scatter/gather across any pages *outside* the reserved bootmem region. Although it's hard to put it on the command line, since that has to be handled by *userspace*, while the live update state is created *during* the kexec hypercall by Xen itself. We've settled for now on putting that breadcrumb into the start of the reserved bootmem region itself, removing the need for a separate lu_data argument. The series continues at https://xenbits.xen.org/gitweb/?p=people/dwmw2/xen.git;a=shortlog;h=refs/heads/lu-master and has reached the point where I can write "Hello World" to a live update data stream and then frown grumpily at the next Xen telling me (XEN) 1 pages of live update data at 23e24d000 (XEN) First live update data page at MFN 23ea34: (XEN) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... because the first data page got zeroed during the transition. I'll fix that, implement the code which actually excludes busy pages from being registered in the heap (and fix up the fact that bad pages above HYPERVISOR_VIRT_END are also not being dropped as they should, while I'm at it), and post a second set for comment. I'm mostly after feedback on the direction (of which the comment about how the first mapping succeeds was massively useful; thanks!) than the finer details of the implementation at this point. It's just that code is sometimes a better explanation of what I mean, than prose.