9 #include <linux/module.h>
10 #include <linux/list.h>
12 #include <linux/slab.h>
13 #include <asm/pgalloc.h>
14 #include <asm/pgtable.h>
15 #include <asm/setup.h>
16 #include <asm/tlbflush.h>
17 #include <asm/sections.h>
29 static void __ref *vmem_alloc_pages(
unsigned int order)
36 static inline pud_t *vmem_pud_alloc(
void)
41 pud = vmem_alloc_pages(2);
44 clear_table((
unsigned long *) pud, _REGION3_ENTRY_EMPTY,
PAGE_SIZE * 4);
49 static inline pmd_t *vmem_pmd_alloc(
void)
54 pmd = vmem_alloc_pages(2);
80 static int vmem_add_mem(
unsigned long start,
unsigned long size,
int ro)
82 unsigned long end = start +
size;
83 unsigned long address =
start;
91 while (address < end) {
94 pu_dir = vmem_pud_alloc();
102 pm_dir = vmem_pmd_alloc();
111 #if defined(CONFIG_64BIT) && !defined(CONFIG_DEBUG_PAGEALLOC)
114 pte_val(pte) |= _SEGMENT_ENTRY_LARGE;
121 pt_dir = vmem_pte_alloc(address);
141 static void vmem_remove_range(
unsigned long start,
unsigned long size)
143 unsigned long end = start +
size;
144 unsigned long address =
start;
152 while (address < end) {
193 start_addr = (
unsigned long) start;
194 end_addr = (
unsigned long) (start + nr);
196 for (address = start_addr; address < end_addr; address +=
PAGE_SIZE) {
199 pu_dir = vmem_pud_alloc();
207 pm_dir = vmem_pmd_alloc();
215 pt_dir = vmem_pte_alloc(address);
223 unsigned long new_page;
225 new_page =
__pa(vmem_alloc_pages(0));
258 list_add(&seg->
list, &mem_segs);
272 remove_memory_segment(seg);
273 vmem_remove_range(seg->
start, seg->
size);
285 if (seg->
start == start && seg->
size == size)
289 if (seg->
start != start || seg->
size != size)
293 __remove_shared_memory(seg);
313 ret = insert_memory_segment(seg);
317 ret = vmem_add_mem(start, size, 0);
323 __remove_shared_memory(seg);
338 unsigned long ro_start, ro_end;
350 if (start >= ro_end || end <= ro_start)
351 vmem_add_mem(start, end - start, 0);
352 else if (start >= ro_start && end <= ro_end)
353 vmem_add_mem(start, end - start, 1);
354 else if (start >= ro_start) {
355 vmem_add_mem(start, ro_end - start, 1);
356 vmem_add_mem(ro_end, end - ro_end, 0);
357 }
else if (end < ro_end) {
358 vmem_add_mem(start, ro_start - start, 0);
359 vmem_add_mem(ro_start, end - ro_start, 1);
361 vmem_add_mem(start, ro_start - start, 0);
362 vmem_add_mem(ro_start, ro_end - ro_start, 1);
363 vmem_add_mem(ro_end, end - ro_end, 0);
372 static int __init vmem_convert_memory_chunk(
void)
386 panic(
"Out of memory...\n");
389 insert_memory_segment(seg);