On 09/07/13 14:38, David Vrabel wrote: > From: David Vrabel <david.vrabel@xxxxxxxxxx> > > If there are UNUSABLE regions in the machine memory map, dom0 will > attempt to map them 1:1 which is not permitted by Xen and the kernel > will crash. > > There isn't anything interesting in the UNUSABLE region that the dom0 > kernel needs access to so we can avoid making the 1:1 mapping and > leave the region as RAM. > > Since the obtaining the memory map for dom0 and domU are now more > different, refactor each into separate functions. > > This fixes a dom0 boot failure if tboot is used (because tboot was > marking a memory region as UNUSABLE). > > Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx> > Cc: stable@xxxxxxxxxxxxxxx I tested it with Xen 4.1.3-rc and Linux 3.8.13.4 and it is fixing the early boot crash I reported. Tested-by: Aurelien Chartier <aurelien.chartier@xxxxxxxxxx> > --- > arch/x86/xen/setup.c | 114 ++++++++++++++++++++++++++++++++++++++++---------- > 1 files changed, 91 insertions(+), 23 deletions(-) > > diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c > index 94eac5c..3fdb6bd 100644 > --- a/arch/x86/xen/setup.c > +++ b/arch/x86/xen/setup.c > @@ -55,6 +55,91 @@ unsigned long xen_released_pages; > */ > #define EXTRA_MEM_RATIO (10) > > +static int __init xen_get_memory_map_dom0(struct e820entry *map, > + unsigned *nr_entries) > +{ > + struct xen_memory_map memmap; > + unsigned i; > + int ret; > + > + /* > + * Dom0 requires access to machine addresses for BIOS data and > + * MMIO (e.g. PCI) devices. The reset of the kernel expects > + * to be able to access these through a 1:1 p2m mapping. > + * > + * We need to take the pseudo physical memory map and set up > + * 1:1 mappings corresponding to the RESERVED regions and > + * holes in the /machine/ memory map, adding/expanding the RAM > + * region at the end of the map for the relocated RAM. > + * > + * This is more easily done if we just start with the machine > + * memory map. > + * > + * UNUSABLE regions are awkward, they are not interesting to > + * dom0 and Xen won't allow them to be mapped so we want to > + * leave these as RAM in the pseudo physical map. > + * > + * Again, this is easiest if we take the machine memory map > + * and change the UNUSABLE regions to RAM. > + */ > + > + memmap.nr_entries = *nr_entries; > + set_xen_guest_handle(memmap.buffer, map); > + > + ret = HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap); > + if (ret < 0) > + return ret; > + > + for (i = 0; i < memmap.nr_entries; i++) { > + if (map[i].type == E820_UNUSABLE) > + map[i].type = E820_RAM; > + } > + > + *nr_entries = memmap.nr_entries; > + return 0; > +} > + > +static int __init xen_get_memory_map_domu(struct e820entry *map, > + unsigned *nr_entries) > +{ > + struct xen_memory_map memmap; > + int ret; > + > + /* > + * For domUs, use the psuedo-physical memory map. Small typo here. > + * > + * If this is not available, fake up a memory map with a > + * single region containing the initial number of pages. > + */ > + > + memmap.nr_entries = *nr_entries; > + set_xen_guest_handle(memmap.buffer, map); > + > + ret = HYPERVISOR_memory_op(XENMEM_memory_map, &memmap); > + if (ret == -ENOSYS) { > + unsigned long max_pfn = min(MAX_DOMAIN_PAGES, > + xen_start_info->nr_pages); > + memmap.nr_entries = 1; > + map[0].addr = 0ULL; > + map[0].size = PFN_PHYS(max_pfn); > + /* 8MB slack (to balance backend allocations). */ > + map[0].size += 8ULL << 20; > + map[0].type = E820_RAM; > + } else if (ret < 0) > + return ret; > + > + *nr_entries = memmap.nr_entries; > + return 0; > +} > + > +static int __init xen_get_memory_map(struct e820entry *map, unsigned *nr_entries) > +{ > + if (xen_initial_domain()) > + return xen_get_memory_map_dom0(map, nr_entries); > + else > + return xen_get_memory_map_domu(map, nr_entries); > +} > + > static void __init xen_add_extra_mem(u64 start, u64 size) > { > unsigned long pfn; > @@ -319,42 +404,25 @@ static void xen_align_and_add_e820_region(u64 start, u64 size, int type) > char * __init xen_memory_setup(void) > { > static struct e820entry map[E820MAX] __initdata; > + unsigned map_nr_entries = E820MAX; > > unsigned long max_pfn = xen_start_info->nr_pages; > unsigned long long mem_end; > int rc; > - struct xen_memory_map memmap; > unsigned long max_pages; > unsigned long last_pfn = 0; > unsigned long extra_pages = 0; > unsigned long populated; > int i; > - int op; > > max_pfn = min(MAX_DOMAIN_PAGES, max_pfn); > mem_end = PFN_PHYS(max_pfn); > > - memmap.nr_entries = E820MAX; > - set_xen_guest_handle(memmap.buffer, map); > - > - op = xen_initial_domain() ? > - XENMEM_machine_memory_map : > - XENMEM_memory_map; > - rc = HYPERVISOR_memory_op(op, &memmap); > - if (rc == -ENOSYS) { > - BUG_ON(xen_initial_domain()); > - memmap.nr_entries = 1; > - map[0].addr = 0ULL; > - map[0].size = mem_end; > - /* 8MB slack (to balance backend allocations). */ > - map[0].size += 8ULL << 20; > - map[0].type = E820_RAM; > - rc = 0; > - } > + rc = xen_get_memory_map(map, &map_nr_entries); > BUG_ON(rc); > > /* Make sure the Xen-supplied memory map is well-ordered. */ > - sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries); > + sanitize_e820_map(map, map_nr_entries, &map_nr_entries); > > max_pages = xen_get_max_pages(); > if (max_pages > max_pfn) > @@ -366,12 +434,12 @@ char * __init xen_memory_setup(void) > * this are first released. > */ > xen_released_pages = xen_set_identity_and_release( > - map, memmap.nr_entries, max_pfn); > + map, map_nr_entries, max_pfn); > > /* > * Populate back the non-RAM pages and E820 gaps that had been > * released. */ > - populated = xen_populate_chunk(map, memmap.nr_entries, > + populated = xen_populate_chunk(map, map_nr_entries, > max_pfn, &last_pfn, xen_released_pages); > > xen_released_pages -= populated; > @@ -395,7 +463,7 @@ char * __init xen_memory_setup(void) > extra_pages = min(EXTRA_MEM_RATIO * min(max_pfn, PFN_DOWN(MAXMEM)), > extra_pages); > i = 0; > - while (i < memmap.nr_entries) { > + while (i < map_nr_entries) { > u64 addr = map[i].addr; > u64 size = map[i].size; > u32 type = map[i].type; -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html