aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNamhoon Kim <namhoonk@cs.unc.edu>2017-06-05 12:26:29 -0400
committerNamhoon Kim <namhoonk@cs.unc.edu>2017-06-05 12:26:29 -0400
commit9b5f4aab419ba370062e28231f6910292813a9c9 (patch)
tree4bf6486a5b6f389ba52ec5263344fdcf428c769a
parentfa0a28ee893e8e698263b0bbddee8d541d4c86a6 (diff)
per-partition buddy allocator
-rw-r--r--include/linux/gfp.h7
-rw-r--r--include/linux/mmzone.h19
-rw-r--r--include/litmus/page_dev.h2
-rw-r--r--litmus/bank_proc.c22
-rw-r--r--litmus/color_shm.c8
-rw-r--r--litmus/litmus.c39
-rw-r--r--litmus/page_dev.c154
-rw-r--r--mm/page_alloc.c417
-rw-r--r--mm/vmstat.c89
9 files changed, 553 insertions, 204 deletions
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 15928f0647e4..10a4601c558b 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -35,6 +35,7 @@ struct vm_area_struct;
35#define ___GFP_NO_KSWAPD 0x400000u 35#define ___GFP_NO_KSWAPD 0x400000u
36#define ___GFP_OTHER_NODE 0x800000u 36#define ___GFP_OTHER_NODE 0x800000u
37#define ___GFP_WRITE 0x1000000u 37#define ___GFP_WRITE 0x1000000u
38#define ___GFP_COLOR 0x2000000u
38/* If the above are modified, __GFP_BITS_SHIFT may need updating */ 39/* If the above are modified, __GFP_BITS_SHIFT may need updating */
39 40
40/* 41/*
@@ -94,6 +95,7 @@ struct vm_area_struct;
94#define __GFP_NO_KSWAPD ((__force gfp_t)___GFP_NO_KSWAPD) 95#define __GFP_NO_KSWAPD ((__force gfp_t)___GFP_NO_KSWAPD)
95#define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */ 96#define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
96#define __GFP_WRITE ((__force gfp_t)___GFP_WRITE) /* Allocator intends to dirty page */ 97#define __GFP_WRITE ((__force gfp_t)___GFP_WRITE) /* Allocator intends to dirty page */
98#define __GFP_COLOR ((__force gfp_t)___GFP_COLOR) /* Colored page request */
97 99
98/* 100/*
99 * This may seem redundant, but it's a way of annotating false positives vs. 101 * This may seem redundant, but it's a way of annotating false positives vs.
@@ -101,7 +103,7 @@ struct vm_area_struct;
101 */ 103 */
102#define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK) 104#define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK)
103 105
104#define __GFP_BITS_SHIFT 25 /* Room for N __GFP_FOO bits */ 106#define __GFP_BITS_SHIFT 26 /* Room for N __GFP_FOO bits */
105#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) 107#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
106 108
107/* This equals 0, but use constants in case they ever change */ 109/* This equals 0, but use constants in case they ever change */
@@ -146,6 +148,9 @@ struct vm_area_struct;
146/* 4GB DMA on some platforms */ 148/* 4GB DMA on some platforms */
147#define GFP_DMA32 __GFP_DMA32 149#define GFP_DMA32 __GFP_DMA32
148 150
151/* Colored page requests */
152#define GFP_COLOR __GFP_COLOR
153
149/* Convert GFP flags to their corresponding migrate type */ 154/* Convert GFP flags to their corresponding migrate type */
150static inline int gfpflags_to_migratetype(const gfp_t gfp_flags) 155static inline int gfpflags_to_migratetype(const gfp_t gfp_flags)
151{ 156{
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 92084abf3cf5..d28f7ef8228d 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -38,11 +38,13 @@
38/* For page coloring - This address decoding is used in imx6-sabresd 38/* For page coloring - This address decoding is used in imx6-sabresd
39 * platform without bank interleaving . 39 * platform without bank interleaving .
40 */ 40 */
41#define BANK_MASK 0x38000000 41#define BANK_MASK 0x38000000
42#define BANK_SHIFT 27 42#define BANK_SHIFT 27
43 43#define CACHE_MASK 0x0000f000
44#define CACHE_MASK 0x0000f000 44#define CACHE_SHIFT 12
45#define CACHE_SHIFT 12 45#define MAX_NUM_COLOR 16
46#define MAX_NUM_BANK 8
47#define MAX_PARTITIONED_ORDER 3
46 48
47enum { 49enum {
48 MIGRATE_UNMOVABLE, 50 MIGRATE_UNMOVABLE,
@@ -485,7 +487,8 @@ struct zone {
485 ZONE_PADDING(_pad1_) 487 ZONE_PADDING(_pad1_)
486 /* free areas of different sizes */ 488 /* free areas of different sizes */
487 struct free_area free_area[MAX_ORDER]; 489 struct free_area free_area[MAX_ORDER];
488 490 struct free_area free_area_d[NR_CPUS][MAX_PARTITIONED_ORDER];
491
489 /* zone flags, see below */ 492 /* zone flags, see below */
490 unsigned long flags; 493 unsigned long flags;
491 494
@@ -532,7 +535,9 @@ struct zone {
532 /* Set to true when the PG_migrate_skip bits should be cleared */ 535 /* Set to true when the PG_migrate_skip bits should be cleared */
533 bool compact_blockskip_flush; 536 bool compact_blockskip_flush;
534#endif 537#endif
535 538
539 struct list_head color_list[MAX_NUM_COLOR * MAX_NUM_BANK];
540 DECLARE_BITMAP(color_map, MAX_NUM_COLOR*MAX_NUM_BANK);
536 ZONE_PADDING(_pad3_) 541 ZONE_PADDING(_pad3_)
537 /* Zone statistics */ 542 /* Zone statistics */
538 atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS]; 543 atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
diff --git a/include/litmus/page_dev.h b/include/litmus/page_dev.h
index 9dac293651f0..f1791469cba1 100644
--- a/include/litmus/page_dev.h
+++ b/include/litmus/page_dev.h
@@ -26,5 +26,7 @@
26 26
27int llc_partition_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); 27int llc_partition_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos);
28int dram_partition_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos); 28int dram_partition_handler(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos);
29int bank_to_partition(unsigned int bank);
30int is_in_llc_partition(struct page* page, int cpu);
29 31
30#endif /* _LITMUS_PAGE_DEV_H */ \ No newline at end of file 32#endif /* _LITMUS_PAGE_DEV_H */ \ No newline at end of file
diff --git a/litmus/bank_proc.c b/litmus/bank_proc.c
index 097cff177a2d..353d38dbe9d6 100644
--- a/litmus/bank_proc.c
+++ b/litmus/bank_proc.c
@@ -120,26 +120,6 @@ unsigned int two_exp(unsigned int e)
120 return v; 120 return v;
121} 121}
122 122
123unsigned int num_by_bitmask_index(unsigned int bitmask, unsigned int index)
124{
125 unsigned int pos = 0;
126
127 while(true)
128 {
129 if(index ==0 && (bitmask & 1)==1)
130 {
131 break;
132 }
133 if(index !=0 && (bitmask & 1)==1){
134 index--;
135 }
136 pos++;
137 bitmask = bitmask >>1;
138
139 }
140 return pos;
141}
142
143/* helper functions to find the next colored pool index */ 123/* helper functions to find the next colored pool index */
144static inline unsigned int first_index(unsigned long node) 124static inline unsigned int first_index(unsigned long node)
145{ 125{
@@ -160,7 +140,7 @@ static inline unsigned int first_index(unsigned long node)
160 140
161static inline unsigned int last_index(unsigned long node) 141static inline unsigned int last_index(unsigned long node)
162{ 142{
163 unsigned int bank_no = 7, color_no = 15; 143 unsigned int bank_no = NUM_BANKS-1, color_no = NUM_COLORS-1;
164 144
165 while(bank_no >= 0) { 145 while(bank_no >= 0) {
166 if ((bank_partition[node]>>bank_no) & 0x1) 146 if ((bank_partition[node]>>bank_no) & 0x1)
diff --git a/litmus/color_shm.c b/litmus/color_shm.c
index d4913cd5f213..084262335466 100644
--- a/litmus/color_shm.c
+++ b/litmus/color_shm.c
@@ -264,10 +264,10 @@ static int litmus_color_shm_mmap(struct file *filp, struct vm_area_struct *vma)
264 TRACE_CUR("flags=0x%lx prot=0x%lx\n", vma->vm_flags, 264 TRACE_CUR("flags=0x%lx prot=0x%lx\n", vma->vm_flags,
265 pgprot_val(vma->vm_page_prot)); 265 pgprot_val(vma->vm_page_prot));
266out: 266out:
267 color_param.color == 0x00000000; 267 color_param.color = 0x00000000;
268 color_param.bank == 0x00000000; 268 color_param.bank = 0x00000000;
269 color_offset.offset == 0xffffffff; 269 color_offset.offset = 0xffffffff;
270 color_offset.lock == -1; 270 color_offset.lock = -1;
271 271
272 return err; 272 return err;
273 273
diff --git a/litmus/litmus.c b/litmus/litmus.c
index 84446acb0869..1105408e405a 100644
--- a/litmus/litmus.c
+++ b/litmus/litmus.c
@@ -343,15 +343,19 @@ asmlinkage long sys_reservation_destroy(unsigned int reservation_id, int cpu)
343 343
344static unsigned long color_mask; 344static unsigned long color_mask;
345 345
346static inline unsigned long page_color(struct page *page)
347{
348 return ((page_to_phys(page) & color_mask) >> PAGE_SHIFT);
349}
350
351extern int isolate_lru_page(struct page *page); 346extern int isolate_lru_page(struct page *page);
352extern void putback_movable_page(struct page *page); 347extern void putback_movable_page(struct page *page);
353extern struct page *new_alloc_page(struct page *page, unsigned long node, int **x); 348extern struct page *new_alloc_page(struct page *page, unsigned long node, int **x);
354 349
350static struct page *alloc_colored_page(struct page *page, unsigned long node, int **result)
351{
352 struct page *newpage;
353
354 newpage = alloc_pages(GFP_HIGHUSER_MOVABLE|GFP_COLOR, 0);
355
356 return newpage;
357}
358
355#define INVALID_PFN (0xffffffff) 359#define INVALID_PFN (0xffffffff)
356LIST_HEAD(shared_lib_pages); 360LIST_HEAD(shared_lib_pages);
357 361
@@ -479,7 +483,7 @@ asmlinkage long sys_set_page_color(int cpu)
479 483
480 /* Migrate private pages */ 484 /* Migrate private pages */
481 if (!list_empty(&pagelist)) { 485 if (!list_empty(&pagelist)) {
482 ret = migrate_pages(&pagelist, new_alloc_page, NULL, node, MIGRATE_SYNC, MR_SYSCALL); 486 ret = migrate_pages(&pagelist, alloc_colored_page, NULL, node, MIGRATE_SYNC, MR_SYSCALL);
483 TRACE_TASK(current, "%ld pages not migrated.\n", ret); 487 TRACE_TASK(current, "%ld pages not migrated.\n", ret);
484 nr_not_migrated = ret; 488 nr_not_migrated = ret;
485 if (ret) { 489 if (ret) {
@@ -489,7 +493,7 @@ asmlinkage long sys_set_page_color(int cpu)
489 493
490 /* Replicate shared pages */ 494 /* Replicate shared pages */
491 if (!list_empty(&task_shared_pagelist)) { 495 if (!list_empty(&task_shared_pagelist)) {
492 ret = replicate_pages(&task_shared_pagelist, new_alloc_page, NULL, node, MIGRATE_SYNC, MR_SYSCALL); 496 ret = replicate_pages(&task_shared_pagelist, alloc_colored_page, NULL, node, MIGRATE_SYNC, MR_SYSCALL);
493 TRACE_TASK(current, "%ld shared pages not migrated.\n", ret); 497 TRACE_TASK(current, "%ld shared pages not migrated.\n", ret);
494 nr_not_migrated += ret; 498 nr_not_migrated += ret;
495 if (ret) { 499 if (ret) {
@@ -501,12 +505,27 @@ asmlinkage long sys_set_page_color(int cpu)
501 505
502 TRACE_TASK(current, "nr_pages = %d nr_failed = %d nr_not_migrated = %d\n", nr_pages, nr_failed, nr_not_migrated); 506 TRACE_TASK(current, "nr_pages = %d nr_failed = %d nr_not_migrated = %d\n", nr_pages, nr_failed, nr_not_migrated);
503 printk(KERN_INFO "node = %ld, nr_private_pages = %d, nr_shared_pages = %d, nr_failed_to_isolate_lru = %d, nr_not_migrated = %d\n", node, nr_pages, nr_shared_pages, nr_failed, nr_not_migrated); 507 printk(KERN_INFO "node = %ld, nr_private_pages = %d, nr_shared_pages = %d, nr_failed_to_isolate_lru = %d, nr_not_migrated = %d\n", node, nr_pages, nr_shared_pages, nr_failed, nr_not_migrated);
504
505 flush_cache(1);
506 508
507 return nr_not_migrated; 509 return nr_not_migrated;
508} 510}
509 511
512#define BANK_MASK 0x38000000
513#define BANK_SHIFT 27
514#define CACHE_MASK 0x0000f000
515#define CACHE_SHIFT 12
516
517/* Decoding page color, 0~15 */
518static inline unsigned int page_color(struct page *page)
519{
520 return ((page_to_phys(page)& CACHE_MASK) >> CACHE_SHIFT);
521}
522
523/* Decoding page bank number, 0~7 */
524static inline unsigned int page_bank(struct page *page)
525{
526 return ((page_to_phys(page)& BANK_MASK) >> BANK_SHIFT);
527}
528
510/* sys_test_call() is a test system call for debugging */ 529/* sys_test_call() is a test system call for debugging */
511asmlinkage long sys_test_call(unsigned int param) 530asmlinkage long sys_test_call(unsigned int param)
512{ 531{
@@ -549,7 +568,7 @@ asmlinkage long sys_test_call(unsigned int param)
549 continue; 568 continue;
550 } 569 }
551 570
552 TRACE_TASK(current, "addr: %08x, phy: %08x, pfn: %05lx, _mapcount: %d, _count: %d flags: %s%s%s mapping: %p\n", vma_itr->vm_start + PAGE_SIZE*i, page_to_phys(old_page), page_to_pfn(old_page), page_mapcount(old_page), page_count(old_page), vma_itr->vm_flags&VM_READ?"r":"-", vma_itr->vm_flags&VM_WRITE?"w":"-", vma_itr->vm_flags&VM_EXEC?"x":"-", &(old_page->mapping)); 571 TRACE_TASK(current, "addr: %08x, phy: %08x, color: %d, bank: %d, pfn: %05lx, _mapcount: %d, _count: %d flags: %s%s%s mapping: %p\n", vma_itr->vm_start + PAGE_SIZE*i, page_to_phys(old_page), page_color(old_page), page_bank(old_page), page_to_pfn(old_page), page_mapcount(old_page), page_count(old_page), vma_itr->vm_flags&VM_READ?"r":"-", vma_itr->vm_flags&VM_WRITE?"w":"-", vma_itr->vm_flags&VM_EXEC?"x":"-", &(old_page->mapping));
553 put_page(old_page); 572 put_page(old_page);
554 } 573 }
555 vma_itr = vma_itr->vm_next; 574 vma_itr = vma_itr->vm_next;
diff --git a/litmus/page_dev.c b/litmus/page_dev.c
index 1e91b989dae2..8e29e68ed89a 100644
--- a/litmus/page_dev.c
+++ b/litmus/page_dev.c
@@ -7,36 +7,90 @@
7 7
8#include <litmus/page_dev.h> 8#include <litmus/page_dev.h>
9 9
10#define NR_PARTITIONS 9 10// This Address Decoding is used in imx6-sabredsd platform
11#define NUM_BANKS 8
12#define BANK_MASK 0x38000000
13#define BANK_SHIFT 27
14
15#define NUM_COLORS 16
16#define CACHE_MASK 0x0000f000
17#define CACHE_SHIFT 12
18
19#define NR_LLC_PARTITIONS 9
20#define NR_DRAM_PARTITIONS 5
11 21
12struct mutex dev_mutex; 22struct mutex dev_mutex;
13 23
14/* Initial partitions for LLC and DRAM bank */ 24/* Initial partitions for LLC and DRAM bank */
15/* 4 color for each core, all colors for Level C */ 25/* 4 color for each core, all colors for Level C */
16unsigned int llc_partition[NR_PARTITIONS] = { 26unsigned int llc_partition[NR_LLC_PARTITIONS] = {
17 0x00000003, /* Core 0, and Level A*/ 27 0x0000000f, /* Core 0, and Level A*/
18 0x00000003, /* Core 0, and Level B*/ 28 0x0000000f, /* Core 0, and Level B*/
19 0x0000000C, /* Core 1, and Level A*/ 29 0x000000f0, /* Core 1, and Level A*/
20 0x0000000C, /* Core 1, and Level B*/ 30 0x000000f0, /* Core 1, and Level B*/
21 0x00000030, /* Core 2, and Level A*/ 31 0x00000f00, /* Core 2, and Level A*/
22 0x00000030, /* Core 2, and Level B*/ 32 0x00000f00, /* Core 2, and Level B*/
23 0x000000C0, /* Core 3, and Level A*/ 33 0x0000f000, /* Core 3, and Level A*/
24 0x000000C0, /* Core 3, and Level B*/ 34 0x0000f000, /* Core 3, and Level B*/
25 0x0000ffff, /* Level C */ 35 0x0000ffff, /* Level C */
26}; 36};
27 37
28/* 1 bank for each core, 2 banks for Level C */ 38/* 1 bank for each core, 2 banks for Level C */
29unsigned int dram_partition[NR_PARTITIONS] = { 39unsigned int dram_partition[NR_DRAM_PARTITIONS] = {
30 0x00000010, /* Core 0, and Level A*/ 40 0x00000010,
31 0x00000010, /* Core 0, and Level B*/ 41 0x00000020,
32 0x00000020, /* Core 1, and Level A*/ 42 0x00000040,
33 0x00000020, /* Core 1, and Level B*/ 43 0x00000080,
34 0x00000040, /* Core 2, and Level A*/ 44 0x0000000f,
35 0x00000040, /* Core 2, and Level B*/ 45};
36 0x00000080, /* Core 3, and Level A*/ 46/*
37 0x00000080, /* Core 3, and Level B*/ 47unsigned int dram_partition[NR_DRAM_PARTITIONS] = {
38 0x0000000c, /* Level C */ 48 0x00000001,
49 0x00000002,
50 0x00000004,
51 0x00000008,
52 0x000000f0,
39}; 53};
54*/
55
56/* Decoding page color, 0~15 */
57static inline unsigned int page_color(struct page *page)
58{
59 return ((page_to_phys(page)& CACHE_MASK) >> CACHE_SHIFT);
60}
61
62/* Decoding page bank number, 0~7 */
63static inline unsigned int page_bank(struct page *page)
64{
65 return ((page_to_phys(page)& BANK_MASK) >> BANK_SHIFT);
66}
67
68int bank_to_partition(unsigned int bank)
69{
70 int i;
71 unsigned int bank_bit = 0x1<<bank;
72
73 for (i = 0; i<NR_DRAM_PARTITIONS; i++) {
74 if (dram_partition[i] & bank_bit)
75 return i;
76 }
77
78 return -EINVAL;
79}
80
81int is_in_llc_partition(struct page* page, int cpu)
82{
83 int color;
84 unsigned int page_color_bit;
85
86 color = page_color(page);
87 page_color_bit = 1 << color;
88
89 if (cpu == NR_CPUS)
90 return (page_color_bit&llc_partition[cpu*2]);
91 else
92 return (page_color_bit & (llc_partition[cpu*2] | llc_partition[cpu*2+1]));
93}
40 94
41/* Bounds for values */ 95/* Bounds for values */
42unsigned int llc_partition_max = 0x0000ffff; 96unsigned int llc_partition_max = 0x0000ffff;
@@ -129,7 +183,7 @@ static struct ctl_table partition_table[] =
129 .extra2 = &llc_partition_max, 183 .extra2 = &llc_partition_max,
130 }, 184 },
131 { 185 {
132 .procname = "C0_LA_dram", 186 .procname = "C0_dram",
133 .mode = 0666, 187 .mode = 0666,
134 .proc_handler = dram_partition_handler, 188 .proc_handler = dram_partition_handler,
135 .data = &dram_partition[0], 189 .data = &dram_partition[0],
@@ -138,34 +192,34 @@ static struct ctl_table partition_table[] =
138 .extra2 = &dram_partition_max, 192 .extra2 = &dram_partition_max,
139 }, 193 },
140 { 194 {
141 .procname = "C0_LB_dram", 195 .procname = "C1_dram",
142 .mode = 0666, 196 .mode = 0666,
143 .proc_handler = dram_partition_handler, 197 .proc_handler = dram_partition_handler,
144 .data = &dram_partition[1], 198 .data = &dram_partition[1],
145 .maxlen = sizeof(llc_partition[1]), 199 .maxlen = sizeof(llc_partition[1]),
146 .extra1 = &dram_partition_min, 200 .extra1 = &dram_partition_min,
147 .extra2 = &dram_partition_max, 201 .extra2 = &dram_partition_max,
148 }, 202 },
149 { 203 {
150 .procname = "C1_LA_dram", 204 .procname = "C2_dram",
151 .mode = 0666, 205 .mode = 0666,
152 .proc_handler = dram_partition_handler, 206 .proc_handler = dram_partition_handler,
153 .data = &dram_partition[2], 207 .data = &dram_partition[2],
154 .maxlen = sizeof(llc_partition[2]), 208 .maxlen = sizeof(llc_partition[2]),
155 .extra1 = &dram_partition_min, 209 .extra1 = &dram_partition_min,
156 .extra2 = &dram_partition_max, 210 .extra2 = &dram_partition_max,
157 }, 211 },
158 { 212 {
159 .procname = "C1_LB_dram", 213 .procname = "C3_dram",
160 .mode = 0666, 214 .mode = 0666,
161 .proc_handler = dram_partition_handler, 215 .proc_handler = dram_partition_handler,
162 .data = &dram_partition[3], 216 .data = &dram_partition[3],
163 .maxlen = sizeof(llc_partition[3]), 217 .maxlen = sizeof(llc_partition[3]),
164 .extra1 = &dram_partition_min, 218 .extra1 = &dram_partition_min,
165 .extra2 = &dram_partition_max, 219 .extra2 = &dram_partition_max,
166 }, 220 },
167 { 221 {
168 .procname = "C2_LA_dram", 222 .procname = "CS_dram",
169 .mode = 0666, 223 .mode = 0666,
170 .proc_handler = dram_partition_handler, 224 .proc_handler = dram_partition_handler,
171 .data = &dram_partition[4], 225 .data = &dram_partition[4],
@@ -173,42 +227,6 @@ static struct ctl_table partition_table[] =
173 .extra1 = &dram_partition_min, 227 .extra1 = &dram_partition_min,
174 .extra2 = &dram_partition_max, 228 .extra2 = &dram_partition_max,
175 }, 229 },
176 {
177 .procname = "C2_LB_dram",
178 .mode = 0666,
179 .proc_handler = dram_partition_handler,
180 .data = &dram_partition[5],
181 .maxlen = sizeof(llc_partition[5]),
182 .extra1 = &dram_partition_min,
183 .extra2 = &dram_partition_max,
184 },
185 {
186 .procname = "C3_LA_dram",
187 .mode = 0666,
188 .proc_handler = dram_partition_handler,
189 .data = &dram_partition[6],
190 .maxlen = sizeof(llc_partition[6]),
191 .extra1 = &dram_partition_min,
192 .extra2 = &dram_partition_max,
193 },
194 {
195 .procname = "C3_LB_dram",
196 .mode = 0666,
197 .proc_handler = dram_partition_handler,
198 .data = &dram_partition[7],
199 .maxlen = sizeof(llc_partition[7]),
200 .extra1 = &dram_partition_min,
201 .extra2 = &dram_partition_max,
202 },
203 {
204 .procname = "Call_LC_dram",
205 .mode = 0666,
206 .proc_handler = dram_partition_handler,
207 .data = &dram_partition[8],
208 .maxlen = sizeof(llc_partition[8]),
209 .extra1 = &dram_partition_min,
210 .extra2 = &dram_partition_max,
211 },
212 { } 230 { }
213}; 231};
214 232
@@ -232,8 +250,8 @@ int llc_partition_handler(struct ctl_table *table, int write, void __user *buffe
232 goto out; 250 goto out;
233 if (write) { 251 if (write) {
234 printk("New LLC Partition : \n"); 252 printk("New LLC Partition : \n");
235 for(i = 0; i < NR_PARTITIONS; i++) { 253 for(i = 0; i < NR_LLC_PARTITIONS; i++) {
236 printk("llc_partition[%d] = %x\n", i, llc_partition[i]); 254 printk("llc_partition[%d] = 0x%04x\n", i, llc_partition[i]);
237 } 255 }
238 } 256 }
239out: 257out:
@@ -249,8 +267,8 @@ int dram_partition_handler(struct ctl_table *table, int write, void __user *buff
249 if (ret) 267 if (ret)
250 goto out; 268 goto out;
251 if (write) { 269 if (write) {
252 for(i = 0; i < NR_PARTITIONS; i++) { 270 for(i = 0; i < NR_DRAM_PARTITIONS; i++) {
253 printk("dram_partition[%d] = %x\n", i, dram_partition[i]); 271 printk("dram_partition[%d] = 0x%04x\n", i, dram_partition[i]);
254 } 272 }
255 } 273 }
256out: 274out:
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ff2d2830e877..45cce6a34295 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -71,6 +71,26 @@
71#include <asm/div64.h> 71#include <asm/div64.h>
72#include "internal.h" 72#include "internal.h"
73 73
74// This Address Decoding is used in imx6-sabredsd platform
75#define BANK_MASK 0x38000000
76#define BANK_SHIFT 27
77
78#define CACHE_MASK 0x0000f000
79#define CACHE_SHIFT 12
80#define MAX_COLOR_NODE 128
81
82/* Decoding page color, 0~15 */
83static inline unsigned int page_color(struct page *page)
84{
85 return ((page_to_phys(page)& CACHE_MASK) >> CACHE_SHIFT);
86}
87
88/* Decoding page bank number, 0~7 */
89static inline unsigned int page_bank(struct page *page)
90{
91 return ((page_to_phys(page)& BANK_MASK) >> BANK_SHIFT);
92}
93
74/* prevent >1 _updater_ of zone percpu pageset ->high and ->batch fields */ 94/* prevent >1 _updater_ of zone percpu pageset ->high and ->batch fields */
75static DEFINE_MUTEX(pcp_batch_high_lock); 95static DEFINE_MUTEX(pcp_batch_high_lock);
76#define MIN_PERCPU_PAGELIST_FRACTION (8) 96#define MIN_PERCPU_PAGELIST_FRACTION (8)
@@ -583,76 +603,153 @@ static inline void __free_one_page(struct page *page,
583 unsigned long combined_idx; 603 unsigned long combined_idx;
584 unsigned long uninitialized_var(buddy_idx); 604 unsigned long uninitialized_var(buddy_idx);
585 struct page *buddy; 605 struct page *buddy;
586 int max_order = MAX_ORDER; 606 int max_order, parti_no;
607
608 parti_no = bank_to_partition(page_bank(page));
609 BUG_ON(parti_no < 0 || parti_no > NR_CPUS);
610 if (parti_no < 0 || parti_no > NR_CPUS)
611 printk(KERN_ALERT "PART_NO %d\n", parti_no);
612
613 if (parti_no < NR_CPUS)
614 printk(KERN_ALERT "pfn = %lx, part_no = %d order = %d\n", pfn, parti_no, order);
615
616 if (parti_no == NR_CPUS) {
617 max_order = MAX_ORDER;
618
619 VM_BUG_ON(!zone_is_initialized(zone));
620 VM_BUG_ON_PAGE(page->flags & PAGE_FLAGS_CHECK_AT_PREP, page);
621
622 VM_BUG_ON(migratetype == -1);
623 if (is_migrate_isolate(migratetype)) {
624 /*
625 * We restrict max order of merging to prevent merge
626 * between freepages on isolate pageblock and normal
627 * pageblock. Without this, pageblock isolation
628 * could cause incorrect freepage accounting.
629 */
630 max_order = min(MAX_ORDER, pageblock_order + 1);
631 } else {
632 __mod_zone_freepage_state(zone, 1 << order, migratetype);
633 }
587 634
588 VM_BUG_ON(!zone_is_initialized(zone)); 635 page_idx = pfn & ((1 << max_order) - 1);
589 VM_BUG_ON_PAGE(page->flags & PAGE_FLAGS_CHECK_AT_PREP, page); 636
637 VM_BUG_ON_PAGE(page_idx & ((1 << order) - 1), page);
638 VM_BUG_ON_PAGE(bad_range(zone, page), page);
639
640 while (order < max_order - 1) {
641 buddy_idx = __find_buddy_index(page_idx, order);
642 buddy = page + (buddy_idx - page_idx);
643 if (!page_is_buddy(page, buddy, order))
644 break;
645 /*
646 * Our buddy is free or it is CONFIG_DEBUG_PAGEALLOC guard page,
647 * merge with it and move up one order.
648 */
649 if (page_is_guard(buddy)) {
650 clear_page_guard(zone, buddy, order, migratetype);
651 } else {
652 list_del(&buddy->lru);
653 zone->free_area[order].nr_free--;
654 rmv_page_order(buddy);
655 }
656 combined_idx = buddy_idx & page_idx;
657 page = page + (combined_idx - page_idx);
658 page_idx = combined_idx;
659 order++;
660 }
661 set_page_order(page, order);
590 662
591 VM_BUG_ON(migratetype == -1);
592 if (is_migrate_isolate(migratetype)) {
593 /* 663 /*
594 * We restrict max order of merging to prevent merge 664 * If this is not the largest possible page, check if the buddy
595 * between freepages on isolate pageblock and normal 665 * of the next-highest order is free. If it is, it's possible
596 * pageblock. Without this, pageblock isolation 666 * that pages are being freed that will coalesce soon. In case,
597 * could cause incorrect freepage accounting. 667 * that is happening, add the free page to the tail of the list
668 * so it's less likely to be used soon and more likely to be merged
669 * as a higher order page
598 */ 670 */
599 max_order = min(MAX_ORDER, pageblock_order + 1); 671 if ((order < MAX_ORDER-2) && pfn_valid_within(page_to_pfn(buddy))) {
600 } else { 672 struct page *higher_page, *higher_buddy;
601 __mod_zone_freepage_state(zone, 1 << order, migratetype); 673 combined_idx = buddy_idx & page_idx;
602 } 674 higher_page = page + (combined_idx - page_idx);
675 buddy_idx = __find_buddy_index(combined_idx, order + 1);
676 higher_buddy = higher_page + (buddy_idx - combined_idx);
677 if (page_is_buddy(higher_page, higher_buddy, order + 1)) {
678 list_add_tail(&page->lru,
679 &zone->free_area[order].free_list[migratetype]);
680 goto out;
681 }
682 }
603 683
604 page_idx = pfn & ((1 << max_order) - 1); 684 list_add(&page->lru, &zone->free_area[order].free_list[migratetype]);
685out:
686 zone->free_area[order].nr_free++;
687 } else {
688 max_order = MAX_PARTITIONED_ORDER;
605 689
606 VM_BUG_ON_PAGE(page_idx & ((1 << order) - 1), page); 690 VM_BUG_ON(!zone_is_initialized(zone));
607 VM_BUG_ON_PAGE(bad_range(zone, page), page); 691 VM_BUG_ON_PAGE(page->flags & PAGE_FLAGS_CHECK_AT_PREP, page);
608 692
609 while (order < max_order - 1) { 693 VM_BUG_ON(migratetype == -1);
610 buddy_idx = __find_buddy_index(page_idx, order); 694 if (is_migrate_isolate(migratetype)) {
611 buddy = page + (buddy_idx - page_idx); 695 max_order = min(MAX_PARTITIONED_ORDER, pageblock_order + 1);
612 if (!page_is_buddy(page, buddy, order))
613 break;
614 /*
615 * Our buddy is free or it is CONFIG_DEBUG_PAGEALLOC guard page,
616 * merge with it and move up one order.
617 */
618 if (page_is_guard(buddy)) {
619 clear_page_guard(zone, buddy, order, migratetype);
620 } else { 696 } else {
621 list_del(&buddy->lru); 697 __mod_zone_freepage_state(zone, 1 << order, migratetype);
622 zone->free_area[order].nr_free--;
623 rmv_page_order(buddy);
624 } 698 }
625 combined_idx = buddy_idx & page_idx;
626 page = page + (combined_idx - page_idx);
627 page_idx = combined_idx;
628 order++;
629 }
630 set_page_order(page, order);
631 699
632 /* 700 page_idx = pfn & ((1 << max_order) - 1);
633 * If this is not the largest possible page, check if the buddy 701
634 * of the next-highest order is free. If it is, it's possible 702 VM_BUG_ON_PAGE(page_idx & ((1 << order) - 1), page);
635 * that pages are being freed that will coalesce soon. In case, 703 VM_BUG_ON_PAGE(bad_range(zone, page), page);
636 * that is happening, add the free page to the tail of the list 704
637 * so it's less likely to be used soon and more likely to be merged 705 while (order < max_order - 1) {
638 * as a higher order page 706 buddy_idx = __find_buddy_index(page_idx, order);
639 */ 707 buddy = page + (buddy_idx - page_idx);
640 if ((order < MAX_ORDER-2) && pfn_valid_within(page_to_pfn(buddy))) { 708 if (!page_is_buddy(page, buddy, order))
641 struct page *higher_page, *higher_buddy; 709 break;
642 combined_idx = buddy_idx & page_idx; 710
643 higher_page = page + (combined_idx - page_idx); 711 if (page_is_guard(buddy)) {
644 buddy_idx = __find_buddy_index(combined_idx, order + 1); 712 clear_page_guard(zone, buddy, order, migratetype);
645 higher_buddy = higher_page + (buddy_idx - combined_idx); 713 } else {
646 if (page_is_buddy(higher_page, higher_buddy, order + 1)) { 714 list_del(&buddy->lru);
647 list_add_tail(&page->lru, 715 zone->free_area_d[parti_no][order].nr_free--;
648 &zone->free_area[order].free_list[migratetype]); 716 rmv_page_order(buddy);
649 goto out; 717 }
718 combined_idx = buddy_idx & page_idx;
719 page = page + (combined_idx - page_idx);
720 page_idx = combined_idx;
721 order++;
722 }
723 set_page_order(page, order);
724
725 if ((order < MAX_PARTITIONED_ORDER-2) && pfn_valid_within(page_to_pfn(buddy))) {
726 struct page *higher_page, *higher_buddy;
727 combined_idx = buddy_idx & page_idx;
728 higher_page = page + (combined_idx - page_idx);
729 buddy_idx = __find_buddy_index(combined_idx, order + 1);
730 higher_buddy = higher_page + (buddy_idx - combined_idx);
731 if (page_is_buddy(higher_page, higher_buddy, order + 1)) {
732 list_add_tail(&page->lru,
733 &zone->free_area_d[parti_no][order].free_list[migratetype]);
734 zone->free_area_d[parti_no][order].nr_free++;
735 return;
736 }
650 } 737 }
651 }
652 738
653 list_add(&page->lru, &zone->free_area[order].free_list[migratetype]); 739 if (order >= MAX_PARTITIONED_ORDER) {
654out: 740 int n_idx = 0;
655 zone->free_area[order].nr_free++; 741 struct page *lower_page;
742 for (n_idx = 0 ; n_idx < (1 << (order - MAX_PARTITIONED_ORDER + 1)); n_idx++) {
743 lower_page = page + (n_idx << (MAX_PARTITIONED_ORDER - 1));
744 set_page_order(lower_page, MAX_PARTITIONED_ORDER-1);
745 list_add(&lower_page->lru, &zone->free_area_d[parti_no][MAX_PARTITIONED_ORDER-1].free_list[migratetype]);
746 zone->free_area_d[parti_no][MAX_PARTITIONED_ORDER-1].nr_free++;
747 }
748 } else {
749 list_add(&page->lru, &zone->free_area_d[parti_no][order].free_list[migratetype]);
750 zone->free_area_d[parti_no][order].nr_free++;
751 }
752 }
656} 753}
657 754
658static inline int free_pages_check(struct page *page) 755static inline int free_pages_check(struct page *page)
@@ -997,34 +1094,140 @@ static int prep_new_page(struct page *page, unsigned int order, gfp_t gfp_flags,
997 return 0; 1094 return 0;
998} 1095}
999 1096
1097/* Kernel page coloring */
1098
1099/* build colored page list */
1100static void build_colored_pages(struct zone *zone, struct page *page, int order)
1101{
1102 int i, color, bank;
1103
1104 list_del(&page->lru);
1105 zone->free_area[order].nr_free--;
1106
1107 /* insert pages to zone->color_list[] */
1108 for (i = 0; i < (1<<order); i++) {
1109 int node;
1110 color = page_color(&page[i]);
1111 bank = page_bank(&page[i]);
1112 node = bank*MAX_NUM_COLOR+color;
1113
1114 INIT_LIST_HEAD(&page[i].lru);
1115 list_add_tail(&page[i].lru, &zone->color_list[node]);
1116 bitmap_set(zone->color_map, node, 1);
1117 zone->free_area[0].nr_free++;
1118 rmv_page_order(&page[i]);
1119 }
1120}
1121
1122int color_seq_index[9] = {
1123 0, /* Core 0, and Level A*/
1124 0, /* Core 0, and Level B*/
1125 0, /* Core 1, and Level A*/
1126 0, /* Core 1, and Level B*/
1127 0, /* Core 2, and Level A*/
1128 0, /* Core 2, and Level B*/
1129 0, /* Core 3, and Level A*/
1130 0, /* Core 3, and Level B*/
1131 0, /* Level C */
1132};
1133
1134/* return a colored page */
1135static inline struct page *get_colored_page(struct zone *zone, unsigned long req_color_map[BITS_TO_LONGS(MAX_COLOR_NODE)], int order, int partition)
1136{
1137 struct page *page;
1138 unsigned int color, bank, index;
1139 int i;
1140 DECLARE_BITMAP(candidate_bit, MAX_COLOR_NODE);
1141
1142 /* if req_color_map does not exist in zone, return NULL */
1143 if (!bitmap_intersects(zone->color_map, req_color_map, MAX_COLOR_NODE))
1144 return NULL;
1145
1146 bitmap_and(candidate_bit, zone->color_map, req_color_map, MAX_COLOR_NODE);
1147 index = color_seq_index[partition];
1148
1149 for_each_set_bit(i, candidate_bit, MAX_COLOR_NODE) {
1150 if (index-- <= 0)
1151 break;
1152 }
1153
1154 BUG_ON(i >= MAX_COLOR_NODE);
1155 BUG_ON(list_empty(&zone->color_list[i]));
1156
1157 page = list_entry(zone->color_list[i].next, struct page, lru);
1158
1159 list_del(&page->lru);
1160
1161 if (list_empty(&zone->color_list[i]))
1162 bitmap_clear(zone->color_map, i, 1);
1163
1164 zone->free_area[0].nr_free--;
1165 color = page_color(page);
1166 bank = page_bank(page);
1167 printk(KERN_INFO "color=%d, bank=%d allocated\n", color, bank);
1168 return page;
1169}
1170
1000/* 1171/*
1001 * Go through the free lists for the given migratetype and remove 1172 * Go through the free lists for the given migratetype and remove
1002 * the smallest available page from the freelists 1173 * the smallest available page from the freelists
1003 */ 1174 */
1004static inline 1175static inline
1005struct page *__rmqueue_smallest(struct zone *zone, unsigned int order, 1176struct page *__rmqueue_smallest(struct zone *zone, unsigned int order,
1006 int migratetype) 1177 int migratetype, int color_req)
1007{ 1178{
1008 unsigned int current_order; 1179 unsigned int current_order;
1009 struct free_area *area; 1180 struct free_area *area;
1010 struct page *page; 1181 struct page *page;
1182 int cpu = raw_smp_processor_id();
1183
1184 if (order == 0 && color_req == 1) {
1185 int found = 0;
1186 /* Colored page request with order = 0 */
1187 if (is_realtime(current))
1188 printk(KERN_INFO "COLORED PAGE IS REQUESTED on CPU%d\n", cpu);
1189 /* Find a page of the appropriate size in the preferred list */
1190 for (current_order = order; current_order < MAX_PARTITIONED_ORDER; ++current_order) {
1191 area = &(zone->free_area_d[cpu][current_order]);
1192 if (list_empty(&area->free_list[migratetype]))
1193 continue;
1194
1195 page = list_entry(area->free_list[migratetype].next,
1196 struct page, lru);
1197 if (is_in_llc_partition(page, cpu))
1198 found = 1;
1199
1200 while(!found) {
1201 page = list_next_entry(page, lru);
1202 if (is_in_llc_partition(page, cpu))
1203 found = 1;
1204 }
1205 list_del(&page->lru);
1206 rmv_page_order(page);
1207 area->nr_free--;
1208 expand(zone, page, order, current_order, area, migratetype);
1209 set_freepage_migratetype(page, migratetype);
1210 return page;
1211 }
1212 } else {
1213 /* Buddy allocator */
1214 /* Find a page of the appropriate size in the preferred list */
1215 for (current_order = order; current_order < MAX_ORDER; ++current_order) {
1216 area = &(zone->free_area[current_order]);
1217 if (list_empty(&area->free_list[migratetype]))
1218 continue;
1011 1219
1012 /* Find a page of the appropriate size in the preferred list */ 1220 page = list_entry(area->free_list[migratetype].next,
1013 for (current_order = order; current_order < MAX_ORDER; ++current_order) { 1221 struct page, lru);
1014 area = &(zone->free_area[current_order]); 1222 list_del(&page->lru);
1015 if (list_empty(&area->free_list[migratetype])) 1223 rmv_page_order(page);
1016 continue; 1224 area->nr_free--;
1017 1225 expand(zone, page, order, current_order, area, migratetype);
1018 page = list_entry(area->free_list[migratetype].next, 1226 set_freepage_migratetype(page, migratetype);
1019 struct page, lru); 1227 return page;
1020 list_del(&page->lru); 1228 }
1021 rmv_page_order(page);
1022 area->nr_free--;
1023 expand(zone, page, order, current_order, area, migratetype);
1024 set_freepage_migratetype(page, migratetype);
1025 return page;
1026 } 1229 }
1027 1230
1028 return NULL; 1231 return NULL;
1029} 1232}
1030 1233
@@ -1050,7 +1253,7 @@ static int fallbacks[MIGRATE_TYPES][4] = {
1050static struct page *__rmqueue_cma_fallback(struct zone *zone, 1253static struct page *__rmqueue_cma_fallback(struct zone *zone,
1051 unsigned int order) 1254 unsigned int order)
1052{ 1255{
1053 return __rmqueue_smallest(zone, order, MIGRATE_CMA); 1256 return __rmqueue_smallest(zone, order, MIGRATE_CMA, 0);
1054} 1257}
1055#else 1258#else
1056static inline struct page *__rmqueue_cma_fallback(struct zone *zone, 1259static inline struct page *__rmqueue_cma_fallback(struct zone *zone,
@@ -1291,12 +1494,12 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype)
1291 * Call me with the zone->lock already held. 1494 * Call me with the zone->lock already held.
1292 */ 1495 */
1293static struct page *__rmqueue(struct zone *zone, unsigned int order, 1496static struct page *__rmqueue(struct zone *zone, unsigned int order,
1294 int migratetype) 1497 int migratetype, int color_req)
1295{ 1498{
1296 struct page *page; 1499 struct page *page;
1297 1500
1298retry_reserve: 1501retry_reserve:
1299 page = __rmqueue_smallest(zone, order, migratetype); 1502 page = __rmqueue_smallest(zone, order, migratetype, color_req);
1300 1503
1301 if (unlikely(!page) && migratetype != MIGRATE_RESERVE) { 1504 if (unlikely(!page) && migratetype != MIGRATE_RESERVE) {
1302 if (migratetype == MIGRATE_MOVABLE) 1505 if (migratetype == MIGRATE_MOVABLE)
@@ -1333,7 +1536,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
1333 1536
1334 spin_lock(&zone->lock); 1537 spin_lock(&zone->lock);
1335 for (i = 0; i < count; ++i) { 1538 for (i = 0; i < count; ++i) {
1336 struct page *page = __rmqueue(zone, order, migratetype); 1539 struct page *page = __rmqueue(zone, order, migratetype, 1);
1337 if (unlikely(page == NULL)) 1540 if (unlikely(page == NULL))
1338 break; 1541 break;
1339 1542
@@ -1543,6 +1746,8 @@ void free_hot_cold_page(struct page *page, bool cold)
1543 unsigned long flags; 1746 unsigned long flags;
1544 unsigned long pfn = page_to_pfn(page); 1747 unsigned long pfn = page_to_pfn(page);
1545 int migratetype; 1748 int migratetype;
1749 unsigned int cpu;
1750 int is_local, is_in_pcp;
1546 1751
1547 if (!free_pages_prepare(page, 0)) 1752 if (!free_pages_prepare(page, 0))
1548 return; 1753 return;
@@ -1566,19 +1771,33 @@ void free_hot_cold_page(struct page *page, bool cold)
1566 } 1771 }
1567 migratetype = MIGRATE_MOVABLE; 1772 migratetype = MIGRATE_MOVABLE;
1568 } 1773 }
1569 1774
1570 pcp = &this_cpu_ptr(zone->pageset)->pcp; 1775 cpu = bank_to_partition(page_bank(page));
1571 if (!cold) 1776 BUG_ON(cpu<0);
1572 list_add(&page->lru, &pcp->lists[migratetype]); 1777
1778 if (cpu == smp_processor_id())
1779 is_local = 1;
1573 else 1780 else
1574 list_add_tail(&page->lru, &pcp->lists[migratetype]); 1781 is_local = 0;
1575 pcp->count++; 1782
1576 if (pcp->count >= pcp->high) { 1783 is_in_pcp = is_in_llc_partition(page, smp_processor_id());
1577 unsigned long batch = READ_ONCE(pcp->batch); 1784 if (cpu != NR_CPUS)
1578 free_pcppages_bulk(zone, batch, pcp); 1785 printk(KERN_ALERT "CPU%d Free order-0 page bank = %d, color = %d, is_local %d is_in_pcp %d\n", smp_processor_id(), page_bank(page), page_color(page), is_local, is_in_pcp);
1579 pcp->count -= batch; 1786 if (is_local && is_in_pcp) {
1787 pcp = &this_cpu_ptr(zone->pageset)->pcp;
1788 if (!cold)
1789 list_add(&page->lru, &pcp->lists[migratetype]);
1790 else
1791 list_add_tail(&page->lru, &pcp->lists[migratetype]);
1792 pcp->count++;
1793 if (pcp->count >= pcp->high) {
1794 unsigned long batch = READ_ONCE(pcp->batch);
1795 free_pcppages_bulk(zone, batch, pcp);
1796 pcp->count -= batch;
1797 }
1798 } else {
1799 __free_page(page);
1580 } 1800 }
1581
1582out: 1801out:
1583 local_irq_restore(flags); 1802 local_irq_restore(flags);
1584} 1803}
@@ -1706,8 +1925,9 @@ struct page *buffered_rmqueue(struct zone *preferred_zone,
1706 unsigned long flags; 1925 unsigned long flags;
1707 struct page *page; 1926 struct page *page;
1708 bool cold = ((gfp_flags & __GFP_COLD) != 0); 1927 bool cold = ((gfp_flags & __GFP_COLD) != 0);
1709 1928 bool colored_req = ((gfp_flags & __GFP_COLOR) != 0);
1710 if (likely(order == 0)) { 1929
1930 if (likely(order == 0) && colored_req) {
1711 struct per_cpu_pages *pcp; 1931 struct per_cpu_pages *pcp;
1712 struct list_head *list; 1932 struct list_head *list;
1713 1933
@@ -1744,7 +1964,7 @@ struct page *buffered_rmqueue(struct zone *preferred_zone,
1744 WARN_ON_ONCE(order > 1); 1964 WARN_ON_ONCE(order > 1);
1745 } 1965 }
1746 spin_lock_irqsave(&zone->lock, flags); 1966 spin_lock_irqsave(&zone->lock, flags);
1747 page = __rmqueue(zone, order, migratetype); 1967 page = __rmqueue(zone, order, migratetype, 0);
1748 spin_unlock(&zone->lock); 1968 spin_unlock(&zone->lock);
1749 if (!page) 1969 if (!page)
1750 goto failed; 1970 goto failed;
@@ -4231,10 +4451,23 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
4231static void __meminit zone_init_free_lists(struct zone *zone) 4451static void __meminit zone_init_free_lists(struct zone *zone)
4232{ 4452{
4233 unsigned int order, t; 4453 unsigned int order, t;
4454 int cpu;
4455
4234 for_each_migratetype_order(order, t) { 4456 for_each_migratetype_order(order, t) {
4235 INIT_LIST_HEAD(&zone->free_area[order].free_list[t]); 4457 INIT_LIST_HEAD(&zone->free_area[order].free_list[t]);
4236 zone->free_area[order].nr_free = 0; 4458 zone->free_area[order].nr_free = 0;
4237 } 4459 }
4460
4461 /* Initialize per-partition free_area data structures */
4462 for (cpu = 0; cpu < NR_CPUS; cpu++) {
4463 for (order = 0; order < MAX_PARTITIONED_ORDER; order++) {
4464 for (t = 0; t < MIGRATE_TYPES; t++) {
4465 INIT_LIST_HEAD(&zone->free_area_d[cpu][order].free_list[t]);
4466 zone->free_area_d[cpu][order].nr_free = 0;
4467 printk(KERN_ALERT "free_area_d[%d][%d].free_list[%d] init.\n", cpu, order, t);
4468 }
4469 }
4470 }
4238} 4471}
4239 4472
4240#ifndef __HAVE_ARCH_MEMMAP_INIT 4473#ifndef __HAVE_ARCH_MEMMAP_INIT
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 4f5cd974e11a..4bbf65f7335b 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -956,6 +956,67 @@ static void pagetypeinfo_showfree_print(struct seq_file *m,
956 } 956 }
957} 957}
958 958
959static void pagetypeinfo_showpartitionfree_print(struct seq_file *m,
960 pg_data_t *pgdat, struct zone *zone, int cpu)
961{
962 int order, mtype;
963
964 for (mtype = 0; mtype < MIGRATE_TYPES; mtype++) {
965 seq_printf(m, "Node %4d, zone %8s, type %12s ",
966 pgdat->node_id,
967 zone->name,
968 migratetype_names[mtype]);
969 for (order = 0; order < MAX_PARTITIONED_ORDER; ++order) {
970 unsigned long freecount = 0;
971 struct free_area *area;
972 struct list_head *curr;
973
974 area = &(zone->free_area_d[cpu][order]);
975
976 list_for_each(curr, &area->free_list[mtype])
977 freecount++;
978 seq_printf(m, "%6lu ", freecount);
979 }
980 seq_putc(m, '\n');
981 }
982}
983
984static void walk_zones_in_node_in_partition(struct seq_file *m, pg_data_t *pgdat,
985 int cpu, void (*print)(struct seq_file *m, pg_data_t *, struct zone *, int))
986{
987 struct zone *zone;
988 struct zone *node_zones = pgdat->node_zones;
989 unsigned long flags;
990
991 for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
992 if (!populated_zone(zone))
993 continue;
994
995 spin_lock_irqsave(&zone->lock, flags);
996 print(m, pgdat, zone, cpu);
997 spin_unlock_irqrestore(&zone->lock, flags);
998 }
999}
1000
1001/* Print out the free pages at each order for each migatetype and partition */
1002static int pagetypeinfo_showpartitioned(struct seq_file *m, void *arg)
1003{
1004 int order, cpu;
1005 pg_data_t *pgdat = (pg_data_t *)arg;
1006
1007 for_each_online_cpu(cpu) {
1008 /* Print header */
1009 seq_putc(m, '\n');
1010 seq_printf(m, "CPU%d %-43s ", cpu, "free pages count per migrate type at order");
1011 for (order = 0; order < MAX_PARTITIONED_ORDER; ++order)
1012 seq_printf(m, "%6d ", order);
1013 seq_putc(m, '\n');
1014
1015 walk_zones_in_node_in_partition(m, pgdat, cpu, pagetypeinfo_showpartitionfree_print);
1016 }
1017 return 0;
1018}
1019
959/* Print out the free pages at each order for each migatetype */ 1020/* Print out the free pages at each order for each migatetype */
960static int pagetypeinfo_showfree(struct seq_file *m, void *arg) 1021static int pagetypeinfo_showfree(struct seq_file *m, void *arg)
961{ 1022{
@@ -1138,7 +1199,7 @@ static int pagetypeinfo_show(struct seq_file *m, void *arg)
1138 pagetypeinfo_showfree(m, pgdat); 1199 pagetypeinfo_showfree(m, pgdat);
1139 pagetypeinfo_showblockcount(m, pgdat); 1200 pagetypeinfo_showblockcount(m, pgdat);
1140 pagetypeinfo_showmixedcount(m, pgdat); 1201 pagetypeinfo_showmixedcount(m, pgdat);
1141 1202 pagetypeinfo_showpartitioned(m, pgdat);
1142 return 0; 1203 return 0;
1143} 1204}
1144 1205
@@ -1180,10 +1241,27 @@ static const struct file_operations pagetypeinfo_file_ops = {
1180 .release = seq_release, 1241 .release = seq_release,
1181}; 1242};
1182 1243
1244#define BANK_MASK 0x38000000
1245#define BANK_SHIFT 27
1246#define CACHE_MASK 0x0000f000
1247#define CACHE_SHIFT 12
1248/* Decoding page bank number, 0~7 */
1249static inline unsigned int page_bank(struct page *page)
1250{
1251 return ((page_to_phys(page)& BANK_MASK) >> BANK_SHIFT);
1252}
1253/* Decoding page color, 0~15 */
1254static inline unsigned int page_color(struct page *page)
1255{
1256 return ((page_to_phys(page)& CACHE_MASK) >> CACHE_SHIFT);
1257}
1258
1183static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, 1259static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
1184 struct zone *zone) 1260 struct zone *zone)
1185{ 1261{
1186 int i; 1262 int i;
1263 int mtype;
1264
1187 seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name); 1265 seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name);
1188 seq_printf(m, 1266 seq_printf(m,
1189 "\n pages free %lu" 1267 "\n pages free %lu"
@@ -1232,6 +1310,15 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
1232 seq_printf(m, "\n vm stats threshold: %d", 1310 seq_printf(m, "\n vm stats threshold: %d",
1233 pageset->stat_threshold); 1311 pageset->stat_threshold);
1234#endif 1312#endif
1313 /* test */
1314 seq_printf(m, "\n");
1315 for (mtype = 0; mtype < MIGRATE_PCPTYPES; mtype++) {
1316 struct page *p;
1317 list_for_each_entry(p, &pageset->pcp.lists[mtype], lru) {
1318 if (p)
1319 seq_printf(m, "page bank = %d color = %d\n", page_bank(p), page_color(p));
1320 }
1321 }
1235 } 1322 }
1236 seq_printf(m, 1323 seq_printf(m,
1237 "\n all_unreclaimable: %u" 1324 "\n all_unreclaimable: %u"