diff options
| author | ChengYang Fu <chengyangfu@gmail.com> | 2015-03-02 15:56:14 -0500 |
|---|---|---|
| committer | ChengYang Fu <chengyangfu@gmail.com> | 2015-03-02 15:56:14 -0500 |
| commit | dec614745fc38feed5f6032a336967e65cc5f007 (patch) | |
| tree | 58171b45e6567261aae5f02213be6e32558817e8 | |
| parent | b98917d2acc10c98d846a674ecb2443fb64206df (diff) | |
Add multiple interfaces for bank_proc.cchengyangfu
| -rw-r--r-- | litmus/bank_proc.c | 185 |
1 files changed, 119 insertions, 66 deletions
diff --git a/litmus/bank_proc.c b/litmus/bank_proc.c index ec04626b43ec..295c450bfbe2 100644 --- a/litmus/bank_proc.c +++ b/litmus/bank_proc.c | |||
| @@ -1,3 +1,9 @@ | |||
| 1 | /* | ||
| 2 | * bank_proc.c -- Implementation of the page coloring for cache and bank partition. | ||
| 3 | * The file will keep a pool of colored pages. Users can require pages with | ||
| 4 | * specific color or bank number. | ||
| 5 | * Part of the code is modified from Jonathan Herman's code | ||
| 6 | */ | ||
| 1 | #include <linux/init.h> | 7 | #include <linux/init.h> |
| 2 | #include <linux/types.h> | 8 | #include <linux/types.h> |
| 3 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
| @@ -14,16 +20,23 @@ | |||
| 14 | 20 | ||
| 15 | #define LITMUS_LOCKDEP_NAME_MAX_LEN 50 | 21 | #define LITMUS_LOCKDEP_NAME_MAX_LEN 50 |
| 16 | 22 | ||
| 17 | // This is Address Decoding for imx6-sabredsd board | 23 | // This Address Decoding is used in imx6-sabredsd platform |
| 18 | #define CACHE_MASK 0x0000f000 | 24 | #define CACHE_MASK 0x0000f000 |
| 19 | #define BANK_MASK 0x00007000 | 25 | #define BANK_MASK 0x00007000 |
| 20 | #define OFFSET_SHIFT 12 | 26 | #define OFFSET_SHIFT 12 |
| 21 | 27 | ||
| 22 | #define PAGES_PER_COLOR 1024 | 28 | #define PAGES_PER_COLOR 1024 |
| 23 | 29 | ||
| 30 | unsigned long used_cachecolor; | ||
| 31 | unsigned long curr_cachecolor; | ||
| 32 | |||
| 33 | |||
| 24 | unsigned long number_banks; | 34 | unsigned long number_banks; |
| 25 | unsigned long number_cachecolors; | 35 | unsigned long number_cachecolors; |
| 26 | 36 | ||
| 37 | /* | ||
| 38 | * Every page list should contain a lock, a list, and a number recording how many pages it store | ||
| 39 | */ | ||
| 27 | struct color_group { | 40 | struct color_group { |
| 28 | spinlock_t lock; | 41 | spinlock_t lock; |
| 29 | char _lock_name[LITMUS_LOCKDEP_NAME_MAX_LEN]; | 42 | char _lock_name[LITMUS_LOCKDEP_NAME_MAX_LEN]; |
| @@ -31,6 +44,10 @@ struct color_group { | |||
| 31 | atomic_t nr_pages; | 44 | atomic_t nr_pages; |
| 32 | }; | 45 | }; |
| 33 | 46 | ||
| 47 | /* | ||
| 48 | * This is old code which is not used in current version | ||
| 49 | */ | ||
| 50 | /* | ||
| 34 | static struct alloced_pages { | 51 | static struct alloced_pages { |
| 35 | spinlock_t lock; | 52 | spinlock_t lock; |
| 36 | struct list_head list; | 53 | struct list_head list; |
| @@ -41,6 +58,7 @@ struct alloced_page { | |||
| 41 | struct vm_area_struct *vma; | 58 | struct vm_area_struct *vma; |
| 42 | struct list_head list; | 59 | struct list_head list; |
| 43 | }; | 60 | }; |
| 61 | */ | ||
| 44 | 62 | ||
| 45 | static struct color_group *color_groups; | 63 | static struct color_group *color_groups; |
| 46 | static struct lock_class_key color_lock_keys[16]; | 64 | static struct lock_class_key color_lock_keys[16]; |
| @@ -59,6 +77,9 @@ static inline unsigned long page_bank(struct page *page) | |||
| 59 | return ((page_to_phys(page)& BANK_MASK) >> PAGE_SHIFT); | 77 | return ((page_to_phys(page)& BANK_MASK) >> PAGE_SHIFT); |
| 60 | } | 78 | } |
| 61 | 79 | ||
| 80 | /* | ||
| 81 | * It is used to determine the smallest number of page lists. | ||
| 82 | */ | ||
| 62 | static unsigned long smallest_nr_pages(void) | 83 | static unsigned long smallest_nr_pages(void) |
| 63 | { | 84 | { |
| 64 | unsigned long i, min_pages = -1; | 85 | unsigned long i, min_pages = -1; |
| @@ -70,8 +91,9 @@ static unsigned long smallest_nr_pages(void) | |||
| 70 | } | 91 | } |
| 71 | return min_pages; | 92 | return min_pages; |
| 72 | } | 93 | } |
| 94 | |||
| 73 | /* | 95 | /* |
| 74 | * Page's count should be one, it sould not be on any LRU list. | 96 | * Add a page to current pool. |
| 75 | */ | 97 | */ |
| 76 | void add_page_to_color_list(struct page *page) | 98 | void add_page_to_color_list(struct page *page) |
| 77 | { | 99 | { |
| @@ -82,10 +104,14 @@ void add_page_to_color_list(struct page *page) | |||
| 82 | spin_lock(&cgroup->lock); | 104 | spin_lock(&cgroup->lock); |
| 83 | list_add_tail(&page->lru, &cgroup->list); | 105 | list_add_tail(&page->lru, &cgroup->list); |
| 84 | atomic_inc(&cgroup->nr_pages); | 106 | atomic_inc(&cgroup->nr_pages); |
| 85 | // SetPageLRU(page); | ||
| 86 | spin_unlock(&cgroup->lock); | 107 | spin_unlock(&cgroup->lock); |
| 87 | } | 108 | } |
| 88 | 109 | ||
| 110 | /* | ||
| 111 | * Replenish the page pool. | ||
| 112 | * If the newly allocate page is what we want, it will be pushed to the correct page list | ||
| 113 | * otherwise, it will be freed. | ||
| 114 | */ | ||
| 89 | static int do_add_pages(void) | 115 | static int do_add_pages(void) |
| 90 | { | 116 | { |
| 91 | printk("LITMUS do add pages\n"); | 117 | printk("LITMUS do add pages\n"); |
| @@ -95,9 +121,9 @@ static int do_add_pages(void) | |||
| 95 | unsigned long color; | 121 | unsigned long color; |
| 96 | int ret = 0; | 122 | int ret = 0; |
| 97 | 123 | ||
| 124 | // until all the page lists contain enough pages | ||
| 98 | while (smallest_nr_pages() < PAGES_PER_COLOR) { | 125 | while (smallest_nr_pages() < PAGES_PER_COLOR) { |
| 99 | 126 | ||
| 100 | //page = alloc_page(GFP_HIGHUSER | __GFP_MOVABLE); | ||
| 101 | page = alloc_page(GFP_HIGHUSER_MOVABLE); | 127 | page = alloc_page(GFP_HIGHUSER_MOVABLE); |
| 102 | 128 | ||
| 103 | if (unlikely(!page)) { | 129 | if (unlikely(!page)) { |
| @@ -107,24 +133,63 @@ static int do_add_pages(void) | |||
| 107 | } | 133 | } |
| 108 | color = page_color(page); | 134 | color = page_color(page); |
| 109 | if (atomic_read(&color_groups[color].nr_pages) < PAGES_PER_COLOR) { | 135 | if (atomic_read(&color_groups[color].nr_pages) < PAGES_PER_COLOR) { |
| 110 | // SetPageReserved(page); | ||
| 111 | add_page_to_color_list(page); | 136 | add_page_to_color_list(page); |
| 112 | } else | 137 | } else{ |
| 138 | // Pages here will be freed later | ||
| 113 | list_add_tail(&page->lru, &free_later); | 139 | list_add_tail(&page->lru, &free_later); |
| 140 | } | ||
| 114 | } | 141 | } |
| 142 | // Free the unwanted pages | ||
| 115 | list_for_each_entry_safe(page, page_tmp, &free_later, lru) { | 143 | list_for_each_entry_safe(page, page_tmp, &free_later, lru) { |
| 116 | list_del(&page->lru); | 144 | list_del(&page->lru); |
| 117 | __free_page(page); | 145 | __free_page(page); |
| 118 | } | 146 | } |
| 119 | /* setup the color queue stuff */ | ||
| 120 | // ret = setup_flusher_array(); | ||
| 121 | out: | 147 | out: |
| 122 | return ret; | 148 | return ret; |
| 123 | } | 149 | } |
| 124 | 150 | ||
| 151 | /* | ||
| 152 | * Provide pages for replacement according cache color | ||
| 153 | * This should be the only implementation here | ||
| 154 | * This function should not be accessed by others directly. | ||
| 155 | * | ||
| 156 | */ | ||
| 157 | static struct page *new_alloc_page_color( unsigned long color) | ||
| 158 | { | ||
| 159 | printk("allocate new page color = %d\n", color); | ||
| 160 | struct color_group *cgroup; | ||
| 161 | struct page *rPage = NULL; | ||
| 162 | |||
| 163 | if( (color <0) || (color)>15) { | ||
| 164 | TRACE_CUR("Wrong color %lu\n", color); | ||
| 165 | printk(KERN_WARNING "Wrong color %lu\n", color); | ||
| 166 | goto out_unlock; | ||
| 167 | } | ||
| 168 | |||
| 169 | |||
| 170 | cgroup = &color_groups[color]; | ||
| 171 | spin_lock(&cgroup->lock); | ||
| 172 | if (unlikely(!atomic_read(&cgroup->nr_pages))) { | ||
| 173 | TRACE_CUR("No free %lu colored pages.\n", color); | ||
| 174 | printk(KERN_WARNING "no free %lu colored pages.\n", color); | ||
| 175 | goto out_unlock; | ||
| 176 | } | ||
| 177 | rPage = list_first_entry(&cgroup->list, struct page, lru); | ||
| 178 | BUG_ON(page_count(rPage) > 1); | ||
| 179 | get_page(rPage); | ||
| 180 | list_del(&rPage->lru); | ||
| 181 | atomic_dec(&cgroup->nr_pages); | ||
| 182 | // ClearPageLRU(rPage); | ||
| 183 | out_unlock: | ||
| 184 | spin_unlock(&cgroup->lock); | ||
| 185 | out: | ||
| 186 | do_add_pages(); | ||
| 187 | return rPage; | ||
| 188 | } | ||
| 189 | |||
| 125 | 190 | ||
| 126 | /* | 191 | /* |
| 127 | * provide pages for replacement | 192 | * provide pages for replacement according to |
| 128 | * node = 0 for Level A, B tasks in Cpu 0 | 193 | * node = 0 for Level A, B tasks in Cpu 0 |
| 129 | * node = 1 for Level A, B tasks in Cpu 1 | 194 | * node = 1 for Level A, B tasks in Cpu 1 |
| 130 | * node = 2 for Level A, B tasks in Cpu 2 | 195 | * node = 2 for Level A, B tasks in Cpu 2 |
| @@ -140,22 +205,7 @@ struct page *new_alloc_page(struct page *page, unsigned long node, int **x) | |||
| 140 | unsigned int color; | 205 | unsigned int color; |
| 141 | get_random_bytes(&color, sizeof(unsigned int)); | 206 | get_random_bytes(&color, sizeof(unsigned int)); |
| 142 | 207 | ||
| 143 | /* | 208 | // Decode the node to decide what color pages we should provide |
| 144 | if(node ==0){ | ||
| 145 | color = (color%2)*8+node; | ||
| 146 | }else if(node == 1){ | ||
| 147 | color = (color%2)*8+node; | ||
| 148 | }else if(node == 2){ | ||
| 149 | color = (color%2)*8+; | ||
| 150 | }else if(node == 3){ | ||
| 151 | color = color%2 + 6; | ||
| 152 | }else if(node == 4){ | ||
| 153 | color = colo | ||
