aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/setup_percpu.c6
-rw-r--r--include/linux/early_res.h1
-rw-r--r--kernel/early_res.c55
-rw-r--r--mm/percpu.c3
4 files changed, 62 insertions, 3 deletions
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 35abcb8b00e9..ef6370b00e70 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -137,7 +137,13 @@ static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
137 137
138static void __init pcpu_fc_free(void *ptr, size_t size) 138static void __init pcpu_fc_free(void *ptr, size_t size)
139{ 139{
140#ifdef CONFIG_NO_BOOTMEM
141 u64 start = __pa(ptr);
142 u64 end = start + size;
143 free_early_partial(start, end);
144#else
140 free_bootmem(__pa(ptr), size); 145 free_bootmem(__pa(ptr), size);
146#endif
141} 147}
142 148
143static int __init pcpu_cpu_distance(unsigned int from, unsigned int to) 149static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
diff --git a/include/linux/early_res.h b/include/linux/early_res.h
index 50f7663bb8b1..29c09f57a13c 100644
--- a/include/linux/early_res.h
+++ b/include/linux/early_res.h
@@ -5,6 +5,7 @@
5extern void reserve_early(u64 start, u64 end, char *name); 5extern void reserve_early(u64 start, u64 end, char *name);
6extern void reserve_early_overlap_ok(u64 start, u64 end, char *name); 6extern void reserve_early_overlap_ok(u64 start, u64 end, char *name);
7extern void free_early(u64 start, u64 end); 7extern void free_early(u64 start, u64 end);
8void free_early_partial(u64 start, u64 end);
8extern void early_res_to_bootmem(u64 start, u64 end); 9extern void early_res_to_bootmem(u64 start, u64 end);
9 10
10void reserve_early_without_check(u64 start, u64 end, char *name); 11void reserve_early_without_check(u64 start, u64 end, char *name);
diff --git a/kernel/early_res.c b/kernel/early_res.c
index aa5494ac4462..9ab11cd84853 100644
--- a/kernel/early_res.c
+++ b/kernel/early_res.c
@@ -61,6 +61,40 @@ static void __init drop_range(int i)
61 early_res_count--; 61 early_res_count--;
62} 62}
63 63
64static void __init drop_range_partial(int i, u64 start, u64 end)
65{
66 u64 common_start, common_end;
67 u64 old_start, old_end;
68
69 old_start = early_res[i].start;
70 old_end = early_res[i].end;
71 common_start = max(old_start, start);
72 common_end = min(old_end, end);
73
74 /* no overlap ? */
75 if (common_start >= common_end)
76 return;
77
78 if (old_start < common_start) {
79 /* make head segment */
80 early_res[i].end = common_start;
81 if (old_end > common_end) {
82 /* add another for left over on tail */
83 reserve_early_without_check(common_end, old_end,
84 early_res[i].name);
85 }
86 return;
87 } else {
88 if (old_end > common_end) {
89 /* reuse the entry for tail left */
90 early_res[i].start = common_end;
91 return;
92 }
93 /* all covered */
94 drop_range(i);
95 }
96}
97
64/* 98/*
65 * Split any existing ranges that: 99 * Split any existing ranges that:
66 * 1) are marked 'overlap_ok', and 100 * 1) are marked 'overlap_ok', and
@@ -284,6 +318,27 @@ void __init free_early(u64 start, u64 end)
284 drop_range(i); 318 drop_range(i);
285} 319}
286 320
321void __init free_early_partial(u64 start, u64 end)
322{
323 struct early_res *r;
324 int i;
325
326try_next:
327 i = find_overlapped_early(start, end);
328 if (i >= max_early_res)
329 return;
330
331 r = &early_res[i];
332 /* hole ? */
333 if (r->end >= end && r->start <= start) {
334 drop_range_partial(i, start, end);
335 return;
336 }
337
338 drop_range_partial(i, start, end);
339 goto try_next;
340}
341
287#ifdef CONFIG_NO_BOOTMEM 342#ifdef CONFIG_NO_BOOTMEM
288static void __init subtract_early_res(struct range *range, int az) 343static void __init subtract_early_res(struct range *range, int az)
289{ 344{
diff --git a/mm/percpu.c b/mm/percpu.c
index 841defeeef86..083e7c91e5f6 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1929,10 +1929,7 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, ssize_t dyn_size,
1929 } 1929 }
1930 /* copy and return the unused part */ 1930 /* copy and return the unused part */
1931 memcpy(ptr, __per_cpu_load, ai->static_size); 1931 memcpy(ptr, __per_cpu_load, ai->static_size);
1932#ifndef CONFIG_NO_BOOTMEM
1933 /* fix partial free ! */
1934 free_fn(ptr + size_sum, ai->unit_size - size_sum); 1932 free_fn(ptr + size_sum, ai->unit_size - size_sum);
1935#endif
1936 } 1933 }
1937 } 1934 }
1938 1935