All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Lalancette <clalance@redhat.com>
To: xen-devel@lists.xensource.com
Subject: [PATCH]: Fix mem= kernel parameter
Date: Tue, 22 May 2007 10:25:58 -0400	[thread overview]
Message-ID: <4652FD76.1010600@redhat.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 2183 bytes --]

All,
     Attached is a patch to fix the mem= parameter to a Xenified kernel, i.e.
/boot/grub/grub.conf:

title RHEL5 i386 Xen (2.6.18-8.1.3.el5xen)
        root (hd0,8)
        kernel /boot/xen.gz-2.6.18-8.1.3.el5 com1=115200,8n1
        module /boot/vmlinuz-2.6.18-8.1.3.el5xen ro root=LABEL=RHEL5_i386 mem=1G
        module /boot/initrd-2.6.18-8.1.3.el5xen.img

While this isn't a common thing to do, it would be nice if this "just worked"
the same way it does on bare-metal, without crashing (which is what it currently
does).  The problem comes down to this piece of code in
arch/[i386,x86_64]/kernel/setup-xen.c:

	/* Make sure we have a correctly sized P->M table. */
	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
		phys_to_machine_mapping = alloc_bootmem_low_pages(
		     max_pfn * sizeof(unsigned long));
		memset(phys_to_machine_mapping, ~0,
		       max_pfn * sizeof(unsigned long));
		memcpy(phys_to_machine_mapping,
		       (unsigned long *)xen_start_info->mfn_list,
		       xen_start_info->nr_pages * sizeof(unsigned long));
		free_bootmem(
		     __pa(xen_start_info->mfn_list),
		     PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
				     sizeof(unsigned long))));

There are really 3 cases that need to be considered:
1) max_pfn == xen_start_info->nr_pages - this is the normal case, when no kernel
or HV parameters are passed when dom0 boots
2)  max_pfn > xen_start_info->nr_pages - this is the case when a domU is
started, and maxmem > memory in the configuration file
3)  max_pfn < xen_start_info->nr_pages - this is the case when specifying mem=
(or highmem= on i386) on the dom0 or domU command line.

The third case is the one that is currently broken.   Looking at the code above,
you can see that the array allocated for the p2m table is too small in that
case, and during the subsequent memcpy() can cause a page fault and then an
OOPs.  The attached patch handles the third case by decreasing the reservation,
and only copying the appropriate number of entries into the p2m table.

The patch is against a 3.0.3-based 2.6.18 kernel, but should apply with
relatively little problem on current unstable.

Comments/question welcome.

Chris Lalancette

[-- Attachment #2: linux-2.6.18-xen-fix-mem-parm7.patch --]
[-- Type: text/x-patch, Size: 3410 bytes --]

--- linux-2.6.18.noarch/arch/i386/kernel/setup-xen.c.orig
+++ linux-2.6.18.noarch/arch/i386/kernel/setup-xen.c
@@ -1553,6 +1553,7 @@ void __init setup_arch(char **cmdline_p)
 	int i, j, k, fpp;
 	struct physdev_set_iopl set_iopl;
 	unsigned long max_low_pfn;
+	unsigned long p2m_pages;
 
 	/* Force a quick death if the kernel panics (not domain 0). */
 	extern int panic_timeout;
@@ -1693,6 +1694,32 @@ void __init setup_arch(char **cmdline_p)
 	find_smp_config();
 #endif
 
+	p2m_pages = max_pfn;
+	if (xen_start_info->nr_pages > max_pfn) {
+		/*
+		 * the max_pfn was shrunk (probably by mem= or highmem=
+		 * kernel parameter); shrink reservation with the HV
+		 */
+		struct xen_memory_reservation reservation = {
+			.address_bits = 0,
+			.extent_order = 0,
+			.domid = DOMID_SELF
+		};
+		unsigned int difference;
+		int ret;
+
+		difference = xen_start_info->nr_pages - max_pfn;
+
+		set_xen_guest_handle(reservation.extent_start,
+				     ((unsigned long *)xen_start_info->mfn_list) + max_pfn);
+		reservation.nr_extents = difference;
+		ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+					   &reservation);
+		BUG_ON (ret != difference);
+	}
+	else if (max_pfn > xen_start_info->nr_pages)
+		p2m_pages = xen_start_info->nr_pages;
+
 	/* Make sure we have a correctly sized P->M table. */
 	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
 		phys_to_machine_mapping = alloc_bootmem_low_pages(
@@ -1701,7 +1728,7 @@ void __init setup_arch(char **cmdline_p)
 		       max_pfn * sizeof(unsigned long));
 		memcpy(phys_to_machine_mapping,
 		       (unsigned long *)xen_start_info->mfn_list,
-		       xen_start_info->nr_pages * sizeof(unsigned long));
+		       p2m_pages * sizeof(unsigned long));
 		free_bootmem(
 		     __pa(xen_start_info->mfn_list),
 		     PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
--- linux-2.6.18.noarch/arch/x86_64/kernel/setup-xen.c.orig
+++ linux-2.6.18.noarch/arch/x86_64/kernel/setup-xen.c
@@ -782,6 +782,33 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_XEN
 	{
 		int i, j, k, fpp;
+		unsigned long p2m_pages;
+
+		p2m_pages = end_pfn;
+		if (xen_start_info->nr_pages > end_pfn) {
+			/*
+			 * the end_pfn was shrunk (probably by mem= or highmem=
+			 * kernel parameter); shrink reservation with the HV
+			 */
+			struct xen_memory_reservation reservation = {
+				.address_bits = 0,
+				.extent_order = 0,
+				.domid = DOMID_SELF
+			};
+			unsigned int difference;
+			int ret;
+			
+			difference = xen_start_info->nr_pages - end_pfn;
+			
+			set_xen_guest_handle(reservation.extent_start,
+					     ((unsigned long *)xen_start_info->mfn_list) + end_pfn);
+			reservation.nr_extents = difference;
+			ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+						   &reservation);
+			BUG_ON (ret != difference);
+		}
+		else if (end_pfn > xen_start_info->nr_pages)
+			p2m_pages = xen_start_info->nr_pages;
 
 		if (!xen_feature(XENFEAT_auto_translated_physmap)) {
 			/* Make sure we have a large enough P->M table. */
@@ -791,7 +818,7 @@ void __init setup_arch(char **cmdline_p)
 			       end_pfn * sizeof(unsigned long));
 			memcpy(phys_to_machine_mapping,
 			       (unsigned long *)xen_start_info->mfn_list,
-			       xen_start_info->nr_pages * sizeof(unsigned long));
+			       p2m_pages * sizeof(unsigned long));
 			free_bootmem(
 				__pa(xen_start_info->mfn_list),
 				PFN_PHYS(PFN_UP(xen_start_info->nr_pages *

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

             reply	other threads:[~2007-05-22 14:25 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-22 14:25 Chris Lalancette [this message]
2007-05-22 16:17 ` [PATCH]: Fix mem= kernel parameter Keir Fraser

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4652FD76.1010600@redhat.com \
    --to=clalance@redhat.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.