]> xenbits.xensource.com Git - people/royger/linux-2.6.18-xen.git/commitdiff
linux-2.6.18/x86: replace order-based range checking of M2P table by linear one
authorJan Beulich <jbeulich@novell.com>
Mon, 25 Jul 2011 12:48:41 +0000 (13:48 +0100)
committerJan Beulich <jbeulich@novell.com>
Mon, 25 Jul 2011 12:48:41 +0000 (13:48 +0100)
The order-based approach is not only less efficient (requiring a shift
and a compare, typical generated code looking like this

        mov     eax, [machine_to_phys_order]
        mov     ecx, eax
        shr     ebx, cl
        test    ebx, ebx
        jnz     ...

whereas a direct check requires just a compare, like in

        cmp     ebx, [machine_to_phys_nr]
        jae     ...

), but also slightly dangerous in the 32-on-64 case - the element
address calculation can wrap if the next power of two boundary is
sufficiently far away from the actual upper limit of the table, and
hence can result in user space addresses being accessed (with it being
unknown what may actually be mapped there).

Signed-off-by: Jan Beulich <jbeulich@novell.com>
arch/i386/mach-xen/setup.c
arch/x86_64/kernel/head64-xen.c
arch/x86_64/mm/init-xen.c
include/asm-i386/mach-xen/asm/maddr.h
include/asm-x86_64/mach-xen/asm/maddr.h

index 8a36ea81519daf1f9ba94393c5e3aa916418b3a8..40a510cdae0f2d3432b2844110fe6765c112e798 100644 (file)
@@ -90,13 +90,12 @@ extern void nmi(void);
 
 unsigned long *machine_to_phys_mapping = (void *)MACH2PHYS_VIRT_START;
 EXPORT_SYMBOL(machine_to_phys_mapping);
-unsigned int machine_to_phys_order;
-EXPORT_SYMBOL(machine_to_phys_order);
+unsigned long machine_to_phys_nr;
+EXPORT_SYMBOL(machine_to_phys_nr);
 
 void __init pre_setup_arch_hook(void)
 {
        struct xen_machphys_mapping mapping;
-       unsigned long machine_to_phys_nr_ents;
        struct xen_platform_parameters pp;
 
        init_mm.pgd = swapper_pg_dir = (pgd_t *)xen_start_info->pt_base;
@@ -108,10 +107,13 @@ void __init pre_setup_arch_hook(void)
 
        if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) {
                machine_to_phys_mapping = (unsigned long *)mapping.v_start;
-               machine_to_phys_nr_ents = mapping.max_mfn + 1;
+               machine_to_phys_nr = mapping.max_mfn + 1;
        } else
-               machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES;
-       machine_to_phys_order = fls(machine_to_phys_nr_ents - 1);
+               machine_to_phys_nr = MACH2PHYS_NR_ENTRIES;
+       if (machine_to_phys_mapping + machine_to_phys_nr
+           < machine_to_phys_mapping)
+               machine_to_phys_nr = (unsigned long *)NULL
+                                    - machine_to_phys_mapping;
 
        if (!xen_feature(XENFEAT_auto_translated_physmap))
                phys_to_machine_mapping =
index a9dab81cd01b5b61ffbaa7f6ed16b73e1088990b..621942d76b818758a7aa1a7af926705f8996685e 100644 (file)
@@ -94,13 +94,12 @@ static void __init setup_boot_cpu_data(void)
 #include <xen/interface/memory.h>
 unsigned long *machine_to_phys_mapping;
 EXPORT_SYMBOL(machine_to_phys_mapping);
-unsigned int machine_to_phys_order;
-EXPORT_SYMBOL(machine_to_phys_order);
+unsigned long machine_to_phys_nr;
+EXPORT_SYMBOL(machine_to_phys_nr);
 
 void __init x86_64_start_kernel(char * real_mode_data)
 {
        struct xen_machphys_mapping mapping;
-       unsigned long machine_to_phys_nr_ents;
        char *s;
        int i;
 
@@ -114,13 +113,11 @@ void __init x86_64_start_kernel(char * real_mode_data)
                xen_start_info->nr_pt_frames;
 
        machine_to_phys_mapping = (unsigned long *)MACH2PHYS_VIRT_START;
-       machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES;
+       machine_to_phys_nr = MACH2PHYS_NR_ENTRIES;
        if (HYPERVISOR_memory_op(XENMEM_machphys_mapping, &mapping) == 0) {
                machine_to_phys_mapping = (unsigned long *)mapping.v_start;
-               machine_to_phys_nr_ents = mapping.max_mfn + 1;
+               machine_to_phys_nr = mapping.max_mfn + 1;
        }
-       while ((1UL << machine_to_phys_order) < machine_to_phys_nr_ents )
-               machine_to_phys_order++;
 
 #if 0
        for (i = 0; i < 256; i++)
index 51a62ec4df354f681f1ac179e7ed305088f72559..95cfc51c75c92a78633bad748582357e03163d95 100644 (file)
@@ -1156,7 +1156,7 @@ int kern_addr_valid(unsigned long addr)
         */
        if (addr >= (unsigned long)machine_to_phys_mapping &&
            addr < (unsigned long)(machine_to_phys_mapping +
-                                  (1UL << machine_to_phys_order)))
+                                  machine_to_phys_nr))
                return 1;
        if (addr >= HYPERVISOR_VIRT_START && addr < HYPERVISOR_VIRT_END)
                return 0;
index 944d063783c8133fc18cc96616b8bce18b4f8f6a..ccce4b98a2f8af425a687b1f1ad944e35289b493 100644 (file)
@@ -25,7 +25,7 @@ extern unsigned long  max_mapnr;
 
 #undef machine_to_phys_mapping
 extern unsigned long *machine_to_phys_mapping;
-extern unsigned int   machine_to_phys_order;
+extern unsigned long  machine_to_phys_nr;
 
 static inline unsigned long pfn_to_mfn(unsigned long pfn)
 {
@@ -50,7 +50,7 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return mfn;
 
-       if (unlikely((mfn >> machine_to_phys_order) != 0))
+       if (unlikely(mfn >= machine_to_phys_nr))
                return max_mapnr;
 
        /* The array access can fail (e.g., device space beyond end of RAM). */
index 0524e2cc2d32ac348d979367e526e4a76342a66e..39084e091f244353b13842aad683421a2afc107a 100644 (file)
@@ -19,7 +19,7 @@ extern unsigned long *phys_to_machine_mapping;
 
 #undef machine_to_phys_mapping
 extern unsigned long *machine_to_phys_mapping;
-extern unsigned int   machine_to_phys_order;
+extern unsigned long  machine_to_phys_nr;
 
 static inline unsigned long pfn_to_mfn(unsigned long pfn)
 {
@@ -44,7 +44,7 @@ static inline unsigned long mfn_to_pfn(unsigned long mfn)
        if (xen_feature(XENFEAT_auto_translated_physmap))
                return mfn;
 
-       if (unlikely((mfn >> machine_to_phys_order) != 0))
+       if (unlikely(mfn >= machine_to_phys_nr))
                return end_pfn;
 
        /* The array access can fail (e.g., device space beyond end of RAM). */