diff options
-rw-r--r-- | arch/x86_64/mm/init.c | 65 | ||||
-rw-r--r-- | arch/x86_64/mm/numa.c | 25 | ||||
-rw-r--r-- | include/asm-x86_64/dma.h | 11 | ||||
-rw-r--r-- | include/asm-x86_64/proto.h | 2 | ||||
-rw-r--r-- | include/linux/gfp.h | 11 | ||||
-rw-r--r-- | include/linux/mmzone.h | 16 | ||||
-rw-r--r-- | mm/page_alloc.c | 15 |
7 files changed, 90 insertions, 55 deletions
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index e60a1a848de8..a1ad4cc423a7 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c | |||
@@ -318,32 +318,51 @@ void zap_low_mappings(void) | |||
318 | flush_tlb_all(); | 318 | flush_tlb_all(); |
319 | } | 319 | } |
320 | 320 | ||
321 | /* Compute zone sizes for the DMA and DMA32 zones in a node. */ | ||
322 | __init void | ||
323 | size_zones(unsigned long *z, unsigned long *h, | ||
324 | unsigned long start_pfn, unsigned long end_pfn) | ||
325 | { | ||
326 | int i; | ||
327 | unsigned long w; | ||
328 | |||
329 | for (i = 0; i < MAX_NR_ZONES; i++) | ||
330 | z[i] = 0; | ||
331 | |||
332 | if (start_pfn < MAX_DMA_PFN) | ||
333 | z[ZONE_DMA] = MAX_DMA_PFN - start_pfn; | ||
334 | if (start_pfn < MAX_DMA32_PFN) { | ||
335 | unsigned long dma32_pfn = MAX_DMA32_PFN; | ||
336 | if (dma32_pfn > end_pfn) | ||
337 | dma32_pfn = end_pfn; | ||
338 | z[ZONE_DMA32] = dma32_pfn - start_pfn; | ||
339 | } | ||
340 | z[ZONE_NORMAL] = end_pfn - start_pfn; | ||
341 | |||
342 | /* Remove lower zones from higher ones. */ | ||
343 | w = 0; | ||
344 | for (i = 0; i < MAX_NR_ZONES; i++) { | ||
345 | if (z[i]) | ||
346 | z[i] -= w; | ||
347 | w += z[i]; | ||
348 | } | ||
349 | |||
350 | /* Compute holes */ | ||
351 | w = 0; | ||
352 | for (i = 0; i < MAX_NR_ZONES; i++) { | ||
353 | unsigned long s = w; | ||
354 | w += z[i]; | ||
355 | h[i] = e820_hole_size(s, w); | ||
356 | } | ||
357 | } | ||
358 | |||
321 | #ifndef CONFIG_NUMA | 359 | #ifndef CONFIG_NUMA |
322 | void __init paging_init(void) | 360 | void __init paging_init(void) |
323 | { | 361 | { |
324 | { | 362 | unsigned long zones[MAX_NR_ZONES], holes[MAX_NR_ZONES]; |
325 | unsigned long zones_size[MAX_NR_ZONES]; | 363 | size_zones(zones, holes, 0, end_pfn); |
326 | unsigned long holes[MAX_NR_ZONES]; | 364 | free_area_init_node(0, NODE_DATA(0), zones, |
327 | unsigned int max_dma; | 365 | __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes); |
328 | |||
329 | memset(zones_size, 0, sizeof(zones_size)); | ||
330 | memset(holes, 0, sizeof(holes)); | ||
331 | |||
332 | max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; | ||
333 | |||
334 | if (end_pfn < max_dma) { | ||
335 | zones_size[ZONE_DMA] = end_pfn; | ||
336 | holes[ZONE_DMA] = e820_hole_size(0, end_pfn); | ||
337 | } else { | ||
338 | zones_size[ZONE_DMA] = max_dma; | ||
339 | holes[ZONE_DMA] = e820_hole_size(0, max_dma); | ||
340 | zones_size[ZONE_NORMAL] = end_pfn - max_dma; | ||
341 | holes[ZONE_NORMAL] = e820_hole_size(max_dma, end_pfn); | ||
342 | } | ||
343 | free_area_init_node(0, NODE_DATA(0), zones_size, | ||
344 | __pa(PAGE_OFFSET) >> PAGE_SHIFT, holes); | ||
345 | } | ||
346 | return; | ||
347 | } | 366 | } |
348 | #endif | 367 | #endif |
349 | 368 | ||
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c index 214803821001..18e86e2eac2d 100644 --- a/arch/x86_64/mm/numa.c +++ b/arch/x86_64/mm/numa.c | |||
@@ -132,29 +132,14 @@ void __init setup_node_zones(int nodeid) | |||
132 | unsigned long start_pfn, end_pfn; | 132 | unsigned long start_pfn, end_pfn; |
133 | unsigned long zones[MAX_NR_ZONES]; | 133 | unsigned long zones[MAX_NR_ZONES]; |
134 | unsigned long holes[MAX_NR_ZONES]; | 134 | unsigned long holes[MAX_NR_ZONES]; |
135 | unsigned long dma_end_pfn; | ||
136 | 135 | ||
137 | memset(zones, 0, sizeof(unsigned long) * MAX_NR_ZONES); | 136 | start_pfn = node_start_pfn(nodeid); |
138 | memset(holes, 0, sizeof(unsigned long) * MAX_NR_ZONES); | 137 | end_pfn = node_end_pfn(nodeid); |
139 | 138 | ||
140 | start_pfn = node_start_pfn(nodeid); | 139 | Dprintk(KERN_INFO "setting up node %d %lx-%lx\n", |
141 | end_pfn = node_end_pfn(nodeid); | 140 | nodeid, start_pfn, end_pfn); |
142 | 141 | ||
143 | Dprintk(KERN_INFO "setting up node %d %lx-%lx\n", nodeid, start_pfn, end_pfn); | 142 | size_zones(zones, holes, start_pfn, end_pfn); |
144 | |||
145 | /* All nodes > 0 have a zero length zone DMA */ | ||
146 | dma_end_pfn = __pa(MAX_DMA_ADDRESS) >> PAGE_SHIFT; | ||
147 | if (start_pfn < dma_end_pfn) { | ||
148 | zones[ZONE_DMA] = dma_end_pfn - start_pfn; | ||
149 | holes[ZONE_DMA] = e820_hole_size(start_pfn, dma_end_pfn); | ||
150 | zones[ZONE_NORMAL] = end_pfn - dma_end_pfn; | ||
151 | holes[ZONE_NORMAL] = e820_hole_size(dma_end_pfn, end_pfn); | ||
152 | |||
153 | } else { | ||
154 | zones[ZONE_NORMAL] = end_pfn - start_pfn; | ||
155 | holes[ZONE_NORMAL] = e820_hole_size(start_pfn, end_pfn); | ||
156 | } | ||
157 | |||
158 | free_area_init_node(nodeid, NODE_DATA(nodeid), zones, | 143 | free_area_init_node(nodeid, NODE_DATA(nodeid), zones, |
159 | start_pfn, holes); | 144 | start_pfn, holes); |
160 | } | 145 | } |
diff --git a/include/asm-x86_64/dma.h b/include/asm-x86_64/dma.h index 16fa3a064d0c..6f2a817b6a7c 100644 --- a/include/asm-x86_64/dma.h +++ b/include/asm-x86_64/dma.h | |||
@@ -72,8 +72,15 @@ | |||
72 | 72 | ||
73 | #define MAX_DMA_CHANNELS 8 | 73 | #define MAX_DMA_CHANNELS 8 |
74 | 74 | ||
75 | /* The maximum address that we can perform a DMA transfer to on this platform */ | 75 | |
76 | #define MAX_DMA_ADDRESS (PAGE_OFFSET+0x1000000) | 76 | /* 16MB ISA DMA zone */ |
77 | #define MAX_DMA_PFN ((16*1024*1024) >> PAGE_SHIFT) | ||
78 | |||
79 | /* 4GB broken PCI/AGP hardware bus master zone */ | ||
80 | #define MAX_DMA32_PFN ((4UL*1024*1024*1024) >> PAGE_SHIFT) | ||
81 | |||
82 | /* Compat define for old dma zone */ | ||
83 | #define MAX_DMA_ADDRESS ((unsigned long)__va(MAX_DMA_PFN << PAGE_SHIFT)) | ||
77 | 84 | ||
78 | /* 8237 DMA controllers */ | 85 | /* 8237 DMA controllers */ |
79 | #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ | 86 | #define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ |
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h index dbb37b0adb43..c251152a0658 100644 --- a/include/asm-x86_64/proto.h +++ b/include/asm-x86_64/proto.h | |||
@@ -22,6 +22,8 @@ extern void mtrr_bp_init(void); | |||
22 | #define mtrr_bp_init() do {} while (0) | 22 | #define mtrr_bp_init() do {} while (0) |
23 | #endif | 23 | #endif |
24 | extern void init_memory_mapping(unsigned long start, unsigned long end); | 24 | extern void init_memory_mapping(unsigned long start, unsigned long end); |
25 | extern void size_zones(unsigned long *z, unsigned long *h, | ||
26 | unsigned long start_pfn, unsigned long end_pfn); | ||
25 | 27 | ||
26 | extern void system_call(void); | 28 | extern void system_call(void); |
27 | extern int kernel_syscall(void); | 29 | extern int kernel_syscall(void); |
diff --git a/include/linux/gfp.h b/include/linux/gfp.h index c3779432a723..4351e6bb5a79 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h | |||
@@ -14,6 +14,13 @@ struct vm_area_struct; | |||
14 | /* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low two bits) */ | 14 | /* Zone modifiers in GFP_ZONEMASK (see linux/mmzone.h - low two bits) */ |
15 | #define __GFP_DMA ((__force gfp_t)0x01u) | 15 | #define __GFP_DMA ((__force gfp_t)0x01u) |
16 | #define __GFP_HIGHMEM ((__force gfp_t)0x02u) | 16 | #define __GFP_HIGHMEM ((__force gfp_t)0x02u) |
17 | #ifdef CONFIG_DMA_IS_DMA32 | ||
18 | #define __GFP_DMA32 ((__force gfp_t)0x01) /* ZONE_DMA is ZONE_DMA32 */ | ||
19 | #elif BITS_PER_LONG < 64 | ||
20 | #define __GFP_DMA32 ((__force gfp_t)0x00) /* ZONE_NORMAL is ZONE_DMA32 */ | ||
21 | #else | ||
22 | #define __GFP_DMA32 ((__force gfp_t)0x04) /* Has own ZONE_DMA32 */ | ||
23 | #endif | ||
17 | 24 | ||
18 | /* | 25 | /* |
19 | * Action modifiers - doesn't change the zoning | 26 | * Action modifiers - doesn't change the zoning |
@@ -64,6 +71,10 @@ struct vm_area_struct; | |||
64 | 71 | ||
65 | #define GFP_DMA __GFP_DMA | 72 | #define GFP_DMA __GFP_DMA |
66 | 73 | ||
74 | /* 4GB DMA on some platforms */ | ||
75 | #define GFP_DMA32 __GFP_DMA32 | ||
76 | |||
77 | |||
67 | #define gfp_zone(mask) ((__force int)((mask) & (__force gfp_t)GFP_ZONEMASK)) | 78 | #define gfp_zone(mask) ((__force int)((mask) & (__force gfp_t)GFP_ZONEMASK)) |
68 | 79 | ||
69 | /* | 80 | /* |
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index f5fa3082fd6a..da7a829f8561 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -71,10 +71,11 @@ struct per_cpu_pageset { | |||
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | #define ZONE_DMA 0 | 73 | #define ZONE_DMA 0 |
74 | #define ZONE_NORMAL 1 | 74 | #define ZONE_DMA32 1 |
75 | #define ZONE_HIGHMEM 2 | 75 | #define ZONE_NORMAL 2 |
76 | #define ZONE_HIGHMEM 3 | ||
76 | 77 | ||
77 | #define MAX_NR_ZONES 3 /* Sync this with ZONES_SHIFT */ | 78 | #define MAX_NR_ZONES 4 /* Sync this with ZONES_SHIFT */ |
78 | #define ZONES_SHIFT 2 /* ceil(log2(MAX_NR_ZONES)) */ | 79 | #define ZONES_SHIFT 2 /* ceil(log2(MAX_NR_ZONES)) */ |
79 | 80 | ||
80 | 81 | ||
@@ -108,9 +109,10 @@ struct per_cpu_pageset { | |||
108 | 109 | ||
109 | /* | 110 | /* |
110 | * On machines where it is needed (eg PCs) we divide physical memory | 111 | * On machines where it is needed (eg PCs) we divide physical memory |
111 | * into multiple physical zones. On a PC we have 3 zones: | 112 | * into multiple physical zones. On a PC we have 4 zones: |
112 | * | 113 | * |
113 | * ZONE_DMA < 16 MB ISA DMA capable memory | 114 | * ZONE_DMA < 16 MB ISA DMA capable memory |
115 | * ZONE_DMA32 0 MB Empty | ||
114 | * ZONE_NORMAL 16-896 MB direct mapped by the kernel | 116 | * ZONE_NORMAL 16-896 MB direct mapped by the kernel |
115 | * ZONE_HIGHMEM > 896 MB only page cache and user processes | 117 | * ZONE_HIGHMEM > 896 MB only page cache and user processes |
116 | */ | 118 | */ |
@@ -455,10 +457,10 @@ extern struct pglist_data contig_page_data; | |||
455 | 457 | ||
456 | #if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED) | 458 | #if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED) |
457 | /* | 459 | /* |
458 | * with 32 bit page->flags field, we reserve 8 bits for node/zone info. | 460 | * with 32 bit page->flags field, we reserve 9 bits for node/zone info. |
459 | * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes. | 461 | * there are 4 zones (3 bits) and this leaves 9-3=6 bits for nodes. |
460 | */ | 462 | */ |
461 | #define FLAGS_RESERVED 8 | 463 | #define FLAGS_RESERVED 9 |
462 | 464 | ||
463 | #elif BITS_PER_LONG == 64 | 465 | #elif BITS_PER_LONG == 64 |
464 | /* | 466 | /* |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 2dbdd98426fd..9b43511dbefd 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -60,8 +60,11 @@ long nr_swap_pages; | |||
60 | * NORMAL allocation will leave 784M/256 of ram reserved in the ZONE_DMA | 60 | * NORMAL allocation will leave 784M/256 of ram reserved in the ZONE_DMA |
61 | * HIGHMEM allocation will leave 224M/32 of ram reserved in ZONE_NORMAL | 61 | * HIGHMEM allocation will leave 224M/32 of ram reserved in ZONE_NORMAL |
62 | * HIGHMEM allocation will (224M+784M)/256 of ram reserved in ZONE_DMA | 62 | * HIGHMEM allocation will (224M+784M)/256 of ram reserved in ZONE_DMA |
63 | * | ||
64 | * TBD: should special case ZONE_DMA32 machines here - in those we normally | ||
65 | * don't need any ZONE_NORMAL reservation | ||
63 | */ | 66 | */ |
64 | int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1] = { 256, 32 }; | 67 | int sysctl_lowmem_reserve_ratio[MAX_NR_ZONES-1] = { 256, 256, 32 }; |
65 | 68 | ||
66 | EXPORT_SYMBOL(totalram_pages); | 69 | EXPORT_SYMBOL(totalram_pages); |
67 | EXPORT_SYMBOL(nr_swap_pages); | 70 | EXPORT_SYMBOL(nr_swap_pages); |
@@ -73,7 +76,7 @@ EXPORT_SYMBOL(nr_swap_pages); | |||
73 | struct zone *zone_table[1 << ZONETABLE_SHIFT] __read_mostly; | 76 | struct zone *zone_table[1 << ZONETABLE_SHIFT] __read_mostly; |
74 | EXPORT_SYMBOL(zone_table); | 77 | EXPORT_SYMBOL(zone_table); |
75 | 78 | ||
76 | static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" }; | 79 | static char *zone_names[MAX_NR_ZONES] = { "DMA", "DMA32", "Normal", "HighMem" }; |
77 | int min_free_kbytes = 1024; | 80 | int min_free_kbytes = 1024; |
78 | 81 | ||
79 | unsigned long __initdata nr_kernel_pages; | 82 | unsigned long __initdata nr_kernel_pages; |
@@ -1442,6 +1445,10 @@ static int __init build_zonelists_node(pg_data_t *pgdat, struct zonelist *zoneli | |||
1442 | zone = pgdat->node_zones + ZONE_NORMAL; | 1445 | zone = pgdat->node_zones + ZONE_NORMAL; |
1443 | if (zone->present_pages) | 1446 | if (zone->present_pages) |
1444 | zonelist->zones[j++] = zone; | 1447 | zonelist->zones[j++] = zone; |
1448 | case ZONE_DMA32: | ||
1449 | zone = pgdat->node_zones + ZONE_DMA32; | ||
1450 | if (zone->present_pages) | ||
1451 | zonelist->zones[j++] = zone; | ||
1445 | case ZONE_DMA: | 1452 | case ZONE_DMA: |
1446 | zone = pgdat->node_zones + ZONE_DMA; | 1453 | zone = pgdat->node_zones + ZONE_DMA; |
1447 | if (zone->present_pages) | 1454 | if (zone->present_pages) |
@@ -1456,6 +1463,8 @@ static inline int highest_zone(int zone_bits) | |||
1456 | int res = ZONE_NORMAL; | 1463 | int res = ZONE_NORMAL; |
1457 | if (zone_bits & (__force int)__GFP_HIGHMEM) | 1464 | if (zone_bits & (__force int)__GFP_HIGHMEM) |
1458 | res = ZONE_HIGHMEM; | 1465 | res = ZONE_HIGHMEM; |
1466 | if (zone_bits & (__force int)__GFP_DMA32) | ||
1467 | res = ZONE_DMA32; | ||
1459 | if (zone_bits & (__force int)__GFP_DMA) | 1468 | if (zone_bits & (__force int)__GFP_DMA) |
1460 | res = ZONE_DMA; | 1469 | res = ZONE_DMA; |
1461 | return res; | 1470 | return res; |
@@ -1976,7 +1985,7 @@ static void __init free_area_init_core(struct pglist_data *pgdat, | |||
1976 | if (zholes_size) | 1985 | if (zholes_size) |
1977 | realsize -= zholes_size[j]; | 1986 | realsize -= zholes_size[j]; |
1978 | 1987 | ||
1979 | if (j == ZONE_DMA || j == ZONE_NORMAL) | 1988 | if (j < ZONE_HIGHMEM) |
1980 | nr_kernel_pages += realsize; | 1989 | nr_kernel_pages += realsize; |
1981 | nr_all_pages += realsize; | 1990 | nr_all_pages += realsize; |
1982 | 1991 | ||