On 09/07/13 19:36, Konrad Rzeszutek Wilk wrote: > On Tue, Jul 09, 2013 at 06:00:17PM +0100, Aurelien Chartier wrote: >> 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. > How did you test it? How can one reproduce this crash? Do you see > this failure with v3.10 or just with v3.8 (and earlier)? I tested it by booting Xen and Linux over tboot (1.7.0) with TXT/TPM enabled. The issue is always reproducible. I posted a log of the kernel panic on xen-devel in May if than can help: http://lists.xen.org/archives/html/xen-devel/2013-05/msg01534.html I did not test with v3.10 yet, but I did not see any commit that could have fixed it. I'll give it a try though. >> 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; >> >> _______________________________________________ >> Xen-devel mailing list >> Xen-devel@xxxxxxxxxxxxx >> http://lists.xen.org/xen-devel -- 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