Commit 27ac792ca0b0a1e7e65f20342260650516c95864
Committed by
Linus Torvalds
1 parent
d92bc31854
Exists in
master
and in
39 other branches
PAGE_ALIGN(): correctly handle 64-bit values on 32-bit architectures
On 32-bit architectures PAGE_ALIGN() truncates 64-bit values to the 32-bit boundary. For example: u64 val = PAGE_ALIGN(size); always returns a value < 4GB even if size is greater than 4GB. The problem resides in PAGE_MASK definition (from include/asm-x86/page.h for example): #define PAGE_SHIFT 12 #define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) ... #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) The "~" is performed on a 32-bit value, so everything in "and" with PAGE_MASK greater than 4GB will be truncated to the 32-bit boundary. Using the ALIGN() macro seems to be the right way, because it uses typeof(addr) for the mask. Also move the PAGE_ALIGN() definitions out of include/asm-*/page.h in include/linux/mm.h. See also lkml discussion: http://lkml.org/lkml/2008/6/11/237 [akpm@linux-foundation.org: fix drivers/media/video/uvc/uvc_queue.c] [akpm@linux-foundation.org: fix v850] [akpm@linux-foundation.org: fix powerpc] [akpm@linux-foundation.org: fix arm] [akpm@linux-foundation.org: fix mips] [akpm@linux-foundation.org: fix drivers/media/video/pvrusb2/pvrusb2-dvb.c] [akpm@linux-foundation.org: fix drivers/mtd/maps/uclinux.c] [akpm@linux-foundation.org: fix powerpc] Signed-off-by: Andrea Righi <righi.andrea@gmail.com> Cc: <linux-arch@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 57 changed files with 36 additions and 74 deletions Side-by-side Diff
- arch/arm/kernel/module.c
- arch/arm/plat-omap/fb.c
- arch/avr32/mm/ioremap.c
- arch/h8300/kernel/setup.c
- arch/m68k/amiga/chipram.c
- arch/m68knommu/kernel/setup.c
- arch/mips/kernel/module.c
- arch/mips/sgi-ip27/ip27-klnuma.c
- arch/powerpc/kernel/suspend.c
- arch/powerpc/lib/code-patching.c
- arch/sparc64/kernel/iommu_common.h
- arch/x86/kernel/module_64.c
- arch/xtensa/kernel/setup.c
- drivers/char/random.c
- drivers/ieee1394/iso.c
- drivers/media/video/pvrusb2/pvrusb2-dvb.c
- drivers/media/video/pvrusb2/pvrusb2-ioread.c
- drivers/media/video/uvc/uvc_queue.c
- drivers/media/video/videobuf-core.c
- drivers/mtd/maps/uclinux.c
- drivers/net/mlx4/eq.c
- drivers/pcmcia/electra_cf.c
- drivers/scsi/sun_esp.c
- drivers/video/acornfb.c
- drivers/video/imxfb.c
- drivers/video/omap/dispc.c
- drivers/video/omap/omapfb_main.c
- drivers/video/pxafb.c
- drivers/video/sa1100fb.c
- include/asm-alpha/page.h
- include/asm-arm/page-nommu.h
- include/asm-arm/page.h
- include/asm-avr32/page.h
- include/asm-blackfin/page.h
- include/asm-cris/page.h
- include/asm-frv/page.h
- include/asm-h8300/page.h
- include/asm-ia64/page.h
- include/asm-m32r/page.h
- include/asm-m68k/dvma.h
- include/asm-m68k/page.h
- include/asm-m68knommu/page.h
- include/asm-mips/page.h
- include/asm-mips/processor.h
- include/asm-mn10300/page.h
- include/asm-parisc/page.h
- include/asm-powerpc/page.h
- include/asm-s390/page.h
- include/asm-sh/page.h
- include/asm-sparc/page_32.h
- include/asm-sparc/page_64.h
- include/asm-um/page.h
- include/asm-v850/page.h
- include/asm-x86/page.h
- include/asm-xtensa/page.h
- include/linux/mm.h
- sound/core/info.c
arch/arm/kernel/module.c
arch/arm/plat-omap/fb.c
arch/avr32/mm/ioremap.c
arch/h8300/kernel/setup.c
arch/m68k/amiga/chipram.c
arch/m68knommu/kernel/setup.c
arch/mips/kernel/module.c
arch/mips/sgi-ip27/ip27-klnuma.c
arch/powerpc/kernel/suspend.c
arch/powerpc/lib/code-patching.c
arch/sparc64/kernel/iommu_common.h
... | ... | @@ -23,7 +23,7 @@ |
23 | 23 | #define IO_PAGE_SHIFT 13 |
24 | 24 | #define IO_PAGE_SIZE (1UL << IO_PAGE_SHIFT) |
25 | 25 | #define IO_PAGE_MASK (~(IO_PAGE_SIZE-1)) |
26 | -#define IO_PAGE_ALIGN(addr) (((addr)+IO_PAGE_SIZE-1)&IO_PAGE_MASK) | |
26 | +#define IO_PAGE_ALIGN(addr) ALIGN(addr, IO_PAGE_SIZE) | |
27 | 27 | |
28 | 28 | #define IO_TSB_ENTRIES (128*1024) |
29 | 29 | #define IO_TSB_SIZE (IO_TSB_ENTRIES * 8) |
arch/x86/kernel/module_64.c
arch/xtensa/kernel/setup.c
drivers/char/random.c
drivers/ieee1394/iso.c
drivers/media/video/pvrusb2/pvrusb2-dvb.c
drivers/media/video/pvrusb2/pvrusb2-ioread.c
drivers/media/video/uvc/uvc_queue.c
drivers/media/video/videobuf-core.c
drivers/mtd/maps/uclinux.c
drivers/net/mlx4/eq.c
drivers/pcmcia/electra_cf.c
drivers/scsi/sun_esp.c
drivers/video/acornfb.c
drivers/video/imxfb.c
drivers/video/omap/dispc.c
drivers/video/omap/omapfb_main.c
drivers/video/pxafb.c
drivers/video/sa1100fb.c
include/asm-alpha/page.h
... | ... | @@ -80,9 +80,6 @@ |
80 | 80 | |
81 | 81 | #endif /* !__ASSEMBLY__ */ |
82 | 82 | |
83 | -/* to align the pointer to the (next) page boundary */ | |
84 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
85 | - | |
86 | 83 | #define __pa(x) ((unsigned long) (x) - PAGE_OFFSET) |
87 | 84 | #define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET)) |
88 | 85 | #ifndef CONFIG_DISCONTIGMEM |
include/asm-arm/page-nommu.h
... | ... | @@ -7,6 +7,7 @@ |
7 | 7 | * it under the terms of the GNU General Public License version 2 as |
8 | 8 | * published by the Free Software Foundation. |
9 | 9 | */ |
10 | + | |
10 | 11 | #ifndef _ASMARM_PAGE_NOMMU_H |
11 | 12 | #define _ASMARM_PAGE_NOMMU_H |
12 | 13 | |
... | ... | @@ -41,9 +42,6 @@ |
41 | 42 | #define __pte(x) (x) |
42 | 43 | #define __pmd(x) (x) |
43 | 44 | #define __pgprot(x) (x) |
44 | - | |
45 | -/* to align the pointer to the (next) page boundary */ | |
46 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
47 | 45 | |
48 | 46 | extern unsigned long memory_start; |
49 | 47 | extern unsigned long memory_end; |
include/asm-arm/page.h
... | ... | @@ -15,9 +15,6 @@ |
15 | 15 | #define PAGE_SIZE (1UL << PAGE_SHIFT) |
16 | 16 | #define PAGE_MASK (~(PAGE_SIZE-1)) |
17 | 17 | |
18 | -/* to align the pointer to the (next) page boundary */ | |
19 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
20 | - | |
21 | 18 | #ifndef __ASSEMBLY__ |
22 | 19 | |
23 | 20 | #ifndef CONFIG_MMU |
include/asm-avr32/page.h
... | ... | @@ -57,9 +57,6 @@ |
57 | 57 | |
58 | 58 | #endif /* !__ASSEMBLY__ */ |
59 | 59 | |
60 | -/* Align the pointer to the (next) page boundary */ | |
61 | -#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) | |
62 | - | |
63 | 60 | /* |
64 | 61 | * The hardware maps the virtual addresses 0x80000000 -> 0x9fffffff |
65 | 62 | * permanently to the physical addresses 0x00000000 -> 0x1fffffff when |
include/asm-blackfin/page.h
... | ... | @@ -51,9 +51,6 @@ |
51 | 51 | #define __pgd(x) ((pgd_t) { (x) } ) |
52 | 52 | #define __pgprot(x) ((pgprot_t) { (x) } ) |
53 | 53 | |
54 | -/* to align the pointer to the (next) page boundary */ | |
55 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
56 | - | |
57 | 54 | extern unsigned long memory_start; |
58 | 55 | extern unsigned long memory_end; |
59 | 56 |
include/asm-cris/page.h
... | ... | @@ -60,9 +60,6 @@ |
60 | 60 | |
61 | 61 | #define page_to_phys(page) __pa((((page) - mem_map) << PAGE_SHIFT) + PAGE_OFFSET) |
62 | 62 | |
63 | -/* to align the pointer to the (next) page boundary */ | |
64 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
65 | - | |
66 | 63 | #ifndef __ASSEMBLY__ |
67 | 64 | |
68 | 65 | #endif /* __ASSEMBLY__ */ |
include/asm-frv/page.h
... | ... | @@ -40,9 +40,6 @@ |
40 | 40 | #define __pgprot(x) ((pgprot_t) { (x) } ) |
41 | 41 | #define PTE_MASK PAGE_MASK |
42 | 42 | |
43 | -/* to align the pointer to the (next) page boundary */ | |
44 | -#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) | |
45 | - | |
46 | 43 | #define devmem_is_allowed(pfn) 1 |
47 | 44 | |
48 | 45 | #define __pa(vaddr) virt_to_phys((void *) (unsigned long) (vaddr)) |
include/asm-h8300/page.h
... | ... | @@ -43,9 +43,6 @@ |
43 | 43 | #define __pgd(x) ((pgd_t) { (x) } ) |
44 | 44 | #define __pgprot(x) ((pgprot_t) { (x) } ) |
45 | 45 | |
46 | -/* to align the pointer to the (next) page boundary */ | |
47 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
48 | - | |
49 | 46 | extern unsigned long memory_start; |
50 | 47 | extern unsigned long memory_end; |
51 | 48 |
include/asm-ia64/page.h
... | ... | @@ -40,7 +40,6 @@ |
40 | 40 | |
41 | 41 | #define PAGE_SIZE (__IA64_UL_CONST(1) << PAGE_SHIFT) |
42 | 42 | #define PAGE_MASK (~(PAGE_SIZE - 1)) |
43 | -#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) | |
44 | 43 | |
45 | 44 | #define PERCPU_PAGE_SHIFT 16 /* log2() of max. size of per-CPU area */ |
46 | 45 | #define PERCPU_PAGE_SIZE (__IA64_UL_CONST(1) << PERCPU_PAGE_SHIFT) |
include/asm-m32r/page.h
... | ... | @@ -41,9 +41,6 @@ |
41 | 41 | |
42 | 42 | #endif /* !__ASSEMBLY__ */ |
43 | 43 | |
44 | -/* to align the pointer to the (next) page boundary */ | |
45 | -#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) | |
46 | - | |
47 | 44 | /* |
48 | 45 | * This handles the memory map.. We could make this a config |
49 | 46 | * option, but too many people screw it up, and too few need |
include/asm-m68k/dvma.h
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | #define DVMA_PAGE_SHIFT 13 |
14 | 14 | #define DVMA_PAGE_SIZE (1UL << DVMA_PAGE_SHIFT) |
15 | 15 | #define DVMA_PAGE_MASK (~(DVMA_PAGE_SIZE-1)) |
16 | -#define DVMA_PAGE_ALIGN(addr) (((addr)+DVMA_PAGE_SIZE-1)&DVMA_PAGE_MASK) | |
16 | +#define DVMA_PAGE_ALIGN(addr) ALIGN(addr, DVMA_PAGE_SIZE) | |
17 | 17 | |
18 | 18 | extern void dvma_init(void); |
19 | 19 | extern int dvma_map_iommu(unsigned long kaddr, unsigned long baddr, |
include/asm-m68k/page.h
... | ... | @@ -103,9 +103,6 @@ |
103 | 103 | #define __pgd(x) ((pgd_t) { (x) } ) |
104 | 104 | #define __pgprot(x) ((pgprot_t) { (x) } ) |
105 | 105 | |
106 | -/* to align the pointer to the (next) page boundary */ | |
107 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
108 | - | |
109 | 106 | #endif /* !__ASSEMBLY__ */ |
110 | 107 | |
111 | 108 | #include <asm/page_offset.h> |
include/asm-m68knommu/page.h
... | ... | @@ -43,9 +43,6 @@ |
43 | 43 | #define __pgd(x) ((pgd_t) { (x) } ) |
44 | 44 | #define __pgprot(x) ((pgprot_t) { (x) } ) |
45 | 45 | |
46 | -/* to align the pointer to the (next) page boundary */ | |
47 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
48 | - | |
49 | 46 | extern unsigned long memory_start; |
50 | 47 | extern unsigned long memory_end; |
51 | 48 |
include/asm-mips/page.h
include/asm-mips/processor.h
... | ... | @@ -45,7 +45,7 @@ |
45 | 45 | * This decides where the kernel will search for a free chunk of vm |
46 | 46 | * space during mmap's. |
47 | 47 | */ |
48 | -#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)) | |
48 | +#define TASK_UNMAPPED_BASE ((TASK_SIZE / 3) & ~(PAGE_SIZE)) | |
49 | 49 | #endif |
50 | 50 | |
51 | 51 | #ifdef CONFIG_64BIT |
include/asm-mn10300/page.h
... | ... | @@ -61,9 +61,6 @@ |
61 | 61 | |
62 | 62 | #endif /* !__ASSEMBLY__ */ |
63 | 63 | |
64 | -/* to align the pointer to the (next) page boundary */ | |
65 | -#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) | |
66 | - | |
67 | 64 | /* |
68 | 65 | * This handles the memory map.. We could make this a config |
69 | 66 | * option, but too many people screw it up, and too few need |
include/asm-parisc/page.h
... | ... | @@ -119,10 +119,6 @@ |
119 | 119 | #define PMD_ENTRY_SIZE (1UL << BITS_PER_PMD_ENTRY) |
120 | 120 | #define PTE_ENTRY_SIZE (1UL << BITS_PER_PTE_ENTRY) |
121 | 121 | |
122 | -/* to align the pointer to the (next) page boundary */ | |
123 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
124 | - | |
125 | - | |
126 | 122 | #define LINUX_GATEWAY_SPACE 0 |
127 | 123 | |
128 | 124 | /* This governs the relationship between virtual and physical addresses. |
include/asm-powerpc/page.h
... | ... | @@ -119,9 +119,6 @@ |
119 | 119 | /* align addr on a size boundary - adjust address up if needed */ |
120 | 120 | #define _ALIGN(addr,size) _ALIGN_UP(addr,size) |
121 | 121 | |
122 | -/* to align the pointer to the (next) page boundary */ | |
123 | -#define PAGE_ALIGN(addr) _ALIGN(addr, PAGE_SIZE) | |
124 | - | |
125 | 122 | /* |
126 | 123 | * Don't compare things with KERNELBASE or PAGE_OFFSET to test for |
127 | 124 | * "kernelness", use is_kernel_addr() - it should do what you want. |
include/asm-s390/page.h
... | ... | @@ -138,9 +138,6 @@ |
138 | 138 | |
139 | 139 | #endif /* !__ASSEMBLY__ */ |
140 | 140 | |
141 | -/* to align the pointer to the (next) page boundary */ | |
142 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
143 | - | |
144 | 141 | #define __PAGE_OFFSET 0x0UL |
145 | 142 | #define PAGE_OFFSET 0x0UL |
146 | 143 | #define __pa(x) (unsigned long)(x) |
include/asm-sh/page.h
... | ... | @@ -22,9 +22,6 @@ |
22 | 22 | #define PAGE_MASK (~(PAGE_SIZE-1)) |
23 | 23 | #define PTE_MASK PAGE_MASK |
24 | 24 | |
25 | -/* to align the pointer to the (next) page boundary */ | |
26 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
27 | - | |
28 | 25 | #if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) |
29 | 26 | #define HPAGE_SHIFT 16 |
30 | 27 | #elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K) |
include/asm-sparc/page_32.h
... | ... | @@ -134,9 +134,6 @@ |
134 | 134 | |
135 | 135 | #endif /* !(__ASSEMBLY__) */ |
136 | 136 | |
137 | -/* to align the pointer to the (next) page boundary */ | |
138 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
139 | - | |
140 | 137 | #define PAGE_OFFSET 0xf0000000 |
141 | 138 | #ifndef __ASSEMBLY__ |
142 | 139 | extern unsigned long phys_base; |
include/asm-sparc/page_64.h
... | ... | @@ -106,9 +106,6 @@ |
106 | 106 | |
107 | 107 | #endif /* !(__ASSEMBLY__) */ |
108 | 108 | |
109 | -/* to align the pointer to the (next) page boundary */ | |
110 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
111 | - | |
112 | 109 | /* We used to stick this into a hard-coded global register (%g4) |
113 | 110 | * but that does not make sense anymore. |
114 | 111 | */ |
include/asm-um/page.h
... | ... | @@ -92,9 +92,6 @@ |
92 | 92 | #define __pgd(x) ((pgd_t) { (x) } ) |
93 | 93 | #define __pgprot(x) ((pgprot_t) { (x) } ) |
94 | 94 | |
95 | -/* to align the pointer to the (next) page boundary */ | |
96 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) | |
97 | - | |
98 | 95 | extern unsigned long uml_physmem; |
99 | 96 | |
100 | 97 | #define PAGE_OFFSET (uml_physmem) |
include/asm-v850/page.h
... | ... | @@ -94,10 +94,6 @@ |
94 | 94 | #endif /* !__ASSEMBLY__ */ |
95 | 95 | |
96 | 96 | |
97 | -/* to align the pointer to the (next) page boundary */ | |
98 | -#define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) | |
99 | - | |
100 | - | |
101 | 97 | /* No current v850 processor has virtual memory. */ |
102 | 98 | #define __virt_to_phys(addr) (addr) |
103 | 99 | #define __phys_to_virt(addr) (addr) |
include/asm-x86/page.h
include/asm-xtensa/page.h
... | ... | @@ -26,13 +26,11 @@ |
26 | 26 | |
27 | 27 | /* |
28 | 28 | * PAGE_SHIFT determines the page size |
29 | - * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary | |
30 | 29 | */ |
31 | 30 | |
32 | 31 | #define PAGE_SHIFT 12 |
33 | 32 | #define PAGE_SIZE (__XTENSA_UL_CONST(1) << PAGE_SHIFT) |
34 | 33 | #define PAGE_MASK (~(PAGE_SIZE-1)) |
35 | -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE - 1) & PAGE_MASK) | |
36 | 34 | |
37 | 35 | #define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR |
38 | 36 | #define MAX_MEM_PFN XCHAL_KSEG_SIZE |
include/linux/mm.h
... | ... | @@ -41,6 +41,9 @@ |
41 | 41 | |
42 | 42 | #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n)) |
43 | 43 | |
44 | +/* to align the pointer to the (next) page boundary */ | |
45 | +#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE) | |
46 | + | |
44 | 47 | /* |
45 | 48 | * Linux kernel virtual memory manager primitives. |
46 | 49 | * The idea being to have a "virtual" mm in the same way |