Re: [Xen-devel] [PATCH] x86/xen: do not identity map E820 memory regions that are UNUSABLE

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

 



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)?
> 
> 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




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]