From: Jan Beulich Date: Mon, 25 Jul 2011 12:48:41 +0000 (+0100) Subject: linux-2.6.18/x86: replace order-based range checking of M2P table by linear one X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=edd166a6d82340ff6bd09c70efb052e76e072b11;p=legacy%2Flinux-2.6.18-xen.git linux-2.6.18/x86: replace order-based range checking of M2P table by linear one 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 --- diff --git a/arch/i386/mach-xen/setup.c b/arch/i386/mach-xen/setup.c index 8a36ea81..40a510cd 100644 --- a/arch/i386/mach-xen/setup.c +++ b/arch/i386/mach-xen/setup.c @@ -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 = diff --git a/arch/x86_64/kernel/head64-xen.c b/arch/x86_64/kernel/head64-xen.c index a9dab81c..621942d7 100644 --- a/arch/x86_64/kernel/head64-xen.c +++ b/arch/x86_64/kernel/head64-xen.c @@ -94,13 +94,12 @@ static void __init setup_boot_cpu_data(void) #include 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++) diff --git a/arch/x86_64/mm/init-xen.c b/arch/x86_64/mm/init-xen.c index 51a62ec4..95cfc51c 100644 --- a/arch/x86_64/mm/init-xen.c +++ b/arch/x86_64/mm/init-xen.c @@ -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; diff --git a/include/asm-i386/mach-xen/asm/maddr.h b/include/asm-i386/mach-xen/asm/maddr.h index 944d0637..ccce4b98 100644 --- a/include/asm-i386/mach-xen/asm/maddr.h +++ b/include/asm-i386/mach-xen/asm/maddr.h @@ -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). */ diff --git a/include/asm-x86_64/mach-xen/asm/maddr.h b/include/asm-x86_64/mach-xen/asm/maddr.h index 0524e2cc..39084e09 100644 --- a/include/asm-x86_64/mach-xen/asm/maddr.h +++ b/include/asm-x86_64/mach-xen/asm/maddr.h @@ -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). */