ia64/xen-unstable

changeset 15192:297d98f057e8

linux: Fix mem= kernel parameter when it is smaller than initial memory allocation.
From: Chris Lalancette <clalance@redhat.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Thu May 24 10:46:57 2007 +0100 (2007-05-24)
parents cc60c18247f1
children 03c213fd2360
files linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c	Thu May 24 10:44:01 2007 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c	Thu May 24 10:46:57 2007 +0100
     1.3 @@ -1583,6 +1583,7 @@ void __init setup_arch(char **cmdline_p)
     1.4  	int i, j, k, fpp;
     1.5  	struct physdev_set_iopl set_iopl;
     1.6  	unsigned long max_low_pfn;
     1.7 +	unsigned long p2m_pages;
     1.8  
     1.9  	/* Force a quick death if the kernel panics (not domain 0). */
    1.10  	extern int panic_timeout;
    1.11 @@ -1725,6 +1726,32 @@ void __init setup_arch(char **cmdline_p)
    1.12  	find_smp_config();
    1.13  #endif
    1.14  
    1.15 +	p2m_pages = max_pfn;
    1.16 +	if (xen_start_info->nr_pages > max_pfn) {
    1.17 +		/*
    1.18 +		 * the max_pfn was shrunk (probably by mem= or highmem=
    1.19 +		 * kernel parameter); shrink reservation with the HV
    1.20 +		 */
    1.21 +		struct xen_memory_reservation reservation = {
    1.22 +			.address_bits = 0,
    1.23 +			.extent_order = 0,
    1.24 +			.domid = DOMID_SELF
    1.25 +		};
    1.26 +		unsigned int difference;
    1.27 +		int ret;
    1.28 +
    1.29 +		difference = xen_start_info->nr_pages - max_pfn;
    1.30 +
    1.31 +		set_xen_guest_handle(reservation.extent_start,
    1.32 +				     ((unsigned long *)xen_start_info->mfn_list) + max_pfn);
    1.33 +		reservation.nr_extents = difference;
    1.34 +		ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
    1.35 +					   &reservation);
    1.36 +		BUG_ON (ret != difference);
    1.37 +	}
    1.38 +	else if (max_pfn > xen_start_info->nr_pages)
    1.39 +		p2m_pages = xen_start_info->nr_pages;
    1.40 +
    1.41  	/* Make sure we have a correctly sized P->M table. */
    1.42  	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
    1.43  		phys_to_machine_mapping = alloc_bootmem_low_pages(
    1.44 @@ -1733,7 +1760,7 @@ void __init setup_arch(char **cmdline_p)
    1.45  		       max_pfn * sizeof(unsigned long));
    1.46  		memcpy(phys_to_machine_mapping,
    1.47  		       (unsigned long *)xen_start_info->mfn_list,
    1.48 -		       xen_start_info->nr_pages * sizeof(unsigned long));
    1.49 +		       p2m_pages * sizeof(unsigned long));
    1.50  		free_bootmem(
    1.51  		     __pa(xen_start_info->mfn_list),
    1.52  		     PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
     2.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c	Thu May 24 10:44:01 2007 +0100
     2.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c	Thu May 24 10:46:57 2007 +0100
     2.3 @@ -792,6 +792,33 @@ void __init setup_arch(char **cmdline_p)
     2.4  #ifdef CONFIG_XEN
     2.5  	{
     2.6  		int i, j, k, fpp;
     2.7 +		unsigned long p2m_pages;
     2.8 +
     2.9 +		p2m_pages = end_pfn;
    2.10 +		if (xen_start_info->nr_pages > end_pfn) {
    2.11 +			/*
    2.12 +			 * the end_pfn was shrunk (probably by mem= or highmem=
    2.13 +			 * kernel parameter); shrink reservation with the HV
    2.14 +			 */
    2.15 +			struct xen_memory_reservation reservation = {
    2.16 +				.address_bits = 0,
    2.17 +				.extent_order = 0,
    2.18 +				.domid = DOMID_SELF
    2.19 +			};
    2.20 +			unsigned int difference;
    2.21 +			int ret;
    2.22 +			
    2.23 +			difference = xen_start_info->nr_pages - end_pfn;
    2.24 +			
    2.25 +			set_xen_guest_handle(reservation.extent_start,
    2.26 +					     ((unsigned long *)xen_start_info->mfn_list) + end_pfn);
    2.27 +			reservation.nr_extents = difference;
    2.28 +			ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
    2.29 +						   &reservation);
    2.30 +			BUG_ON (ret != difference);
    2.31 +		}
    2.32 +		else if (end_pfn > xen_start_info->nr_pages)
    2.33 +			p2m_pages = xen_start_info->nr_pages;
    2.34  
    2.35  		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
    2.36  			/* Make sure we have a large enough P->M table. */
    2.37 @@ -801,7 +828,7 @@ void __init setup_arch(char **cmdline_p)
    2.38  			       end_pfn * sizeof(unsigned long));
    2.39  			memcpy(phys_to_machine_mapping,
    2.40  			       (unsigned long *)xen_start_info->mfn_list,
    2.41 -			       xen_start_info->nr_pages * sizeof(unsigned long));
    2.42 +			       p2m_pages * sizeof(unsigned long));
    2.43  			free_bootmem(
    2.44  				__pa(xen_start_info->mfn_list),
    2.45  				PFN_PHYS(PFN_UP(xen_start_info->nr_pages *