From: kaf24@firebug.cl.cam.ac.uk Date: Thu, 25 Aug 2005 16:21:19 +0000 (+0000) Subject: This patch fixes Bugzilla #169. (It should fix #187 too -- Keir). X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~16844^2~2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=0c01ed49354e4f00fc5cb9994800309b8b0ac99c;p=xen.git This patch fixes Bugzilla #169. (It should fix #187 too -- Keir). The root cause of bug 169 is, machine_to_phys_mapping, starting from 0xffff800000000000, is mapped using 2M pages. When the system has RAM no more than 2G, only one 2M page is allocated and only one PDE entry is created correspondingly, so calling mfn_to_pfn with mfn > 0x80000 will overflow this 2M page and cause a unable handled kernel paging request. The mfn > 0x80000 comes from PCI device I/O memory, here from AGP display card when booting X server. Jun suggested to use something like get_user() when accessing machine_to_phys_mapping. Signed-off-by: Xin Li --- diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h index a18c758658..1bcc85e465 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/page.h @@ -65,8 +65,26 @@ extern unsigned int *phys_to_machine_mapping; #define pfn_to_mfn(pfn) \ ((unsigned long)phys_to_machine_mapping[(unsigned int)(pfn)] & 0x7FFFFFFFUL) -#define mfn_to_pfn(mfn) \ -((unsigned long)machine_to_phys_mapping[(unsigned int)(mfn)]) +static inline unsigned long mfn_to_pfn(unsigned long mfn) +{ + unsigned int pfn; + + /* + * The array access can fail (e.g., device space beyond end of RAM). + * In such cases it doesn't matter what we return (we return garbage), + * but we must handle the fault without crashing! + */ + asm ( + "1: movl %1,%0\n" + "2:\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,2b\n" + ".previous" + : "=r" (pfn) : "m" (machine_to_phys_mapping[mfn]) ); + + return (unsigned long)pfn; +} /* Definitions for machine and pseudophysical addresses. */ #ifdef CONFIG_X86_PAE diff --git a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h index b953737d31..96d5107548 100644 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/page.h @@ -67,8 +67,26 @@ void copy_page(void *, void *); extern u32 *phys_to_machine_mapping; #define pfn_to_mfn(pfn) \ ((unsigned long)phys_to_machine_mapping[(unsigned int)(pfn)] & 0x7FFFFFFFUL) -#define mfn_to_pfn(mfn) \ -((unsigned long)machine_to_phys_mapping[(unsigned int)(mfn)]) +static inline unsigned long mfn_to_pfn(unsigned long mfn) +{ + unsigned int pfn; + + /* + * The array access can fail (e.g., device space beyond end of RAM). + * In such cases it doesn't matter what we return (we return garbage), + * but we must handle the fault without crashing! + */ + asm ( + "1: movl %1,%k0\n" + "2:\n" + ".section __ex_table,\"a\"\n" + " .align 8\n" + " .quad 1b,2b\n" + ".previous" + : "=r" (pfn) : "m" (machine_to_phys_mapping[mfn]) ); + + return (unsigned long)pfn; +} /* Definitions for machine and pseudophysical addresses. */ typedef unsigned long paddr_t;