[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [patch] kexec is not highmem-aware
Hi, The current 2.6.18-xen tree's kexec seems to be working for me OK on x86_64 and on small i686 boxes, but it is broken on >1GB 32-bit configurations, oopsing when the kexec kernel is set up with: BUG: unable to handle kernel NULL pointer dereference at virtual address 00000000 ... CPU: 0 EIP: 0061:[<c0415550>] Not tainted VLI EFLAGS: 00010216 (2.6.18-20.el5.kraxel.7xen #1) EIP is at xen_create_contiguous_region+0x9c/0x44b eax: 00000000 ebx: 00001000 ecx: 00000400 edx: 00000000 esi: 0000000b edi: 00000000 ebp: 00000001 esp: ea292e90 ds: 007b es: 007b ss: 0069 Process kexec (pid: 2439, ti=ea292000 task=ea577aa0 task.ti=ea292000) ... Call Trace: [<c044ac8f>] get_page_from_freelist+0x1c1/0x325 [<c044fc72>] page_address+0x7a/0x81 [<c0438f04>] kimage_alloc_pages+0x64/0xa2 [<c0438fdf>] kimage_alloc_page+0x9d/0x2a5 [<c0439226>] kimage_add_entry+0x3f/0xbd [<c0439780>] sys_kexec_load+0x2a0/0x3f7 [<c040534f>] syscall_call+0x7/0xb ======================= I'm using the kexec code back-ported to the RHEL-5 kernel atm, but current xen-unstable.hg appears to have the same problem. The problem is in kimage_alloc_pages(), which tries to return contiguous pages by calling xen_create_contiguous_region((unsigned long)page_address(pages), order, address_bits) on the pages allocated. Unfortunately, page_address() returns NULL for highmem pages. So as soon as we try this on a page in the highmem heap, we get the above OOPS. Fortunately it's easy to fix: we don't need to call xen_create_contiguous_region() on highmem pages, because the only place I can see in kexec which uses GFP_HIGHMEM also allocates only single pages at a time (and those are by definition always contiguous anyway!) So we really only need to call xen_(create|destroy)_contiguous_region() if order>0. That will continue to do the right thing for lowmem high- order allocations, while allowing single-page GFP_HIGHEM allocations to work. The patch below fixes this for me. --Stephen Don't try to call xen_create_contiguous_region() on highmem pages. It won't work --- page_address() returns NULL on such pages --- but is also unnecesary because the only place in kexec which uses GFP_HIGHMEM also allocates only single pages at a time (and those are by definition always contiguous anyway.) So we really only need to call xen_(create|destroy)_contiguous_region() if order>0. That will continue to do the right thing for lowmem high-order allocations, while allowing single-page GFP_HIGHEM allocations to work. Signed-off-by: Stephen Tweedie <sct@xxxxxxxxxx> --- linux-2.6.18.noarch/kernel/kexec.c.=K0010=.orig +++ linux-2.6.18.noarch/kernel/kexec.c @@ -345,10 +345,13 @@ static struct page *kimage_alloc_pages(g else address_bits = long_log2(limit); - if (xen_create_contiguous_region((unsigned long)page_address(pages), - order, address_bits) < 0) { - __free_pages(pages, order); - return NULL; + if (order > 0) { + BUG_ON(gfp_mask & __GFP_HIGHMEM); + if (xen_create_contiguous_region((unsigned long)page_address(pages), + order, address_bits) < 0) { + __free_pages(pages, order); + return NULL; + } } #endif pages->mapping = NULL; @@ -370,7 +373,8 @@ static void kimage_free_pages(struct pag for (i = 0; i < count; i++) ClearPageReserved(page + i); #ifdef CONFIG_XEN - xen_destroy_contiguous_region((unsigned long)page_address(page), order); + if (order > 0) + xen_destroy_contiguous_region((unsigned long)page_address(page), order); #endif __free_pages(page, order); } _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |