aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze/mm
diff options
context:
space:
mode:
authorMichal Simek <monstr@monstr.eu>2011-12-15 09:02:37 -0500
committerMichal Simek <monstr@monstr.eu>2012-03-23 04:28:13 -0400
commit2f2f371f8907d169650f594850ca6096e2f73b77 (patch)
tree053824b8bd18fdd71119510be569fa0ff7ec0c29 /arch/microblaze/mm
parentbaab8a828d2d6b5b073c192ebe777514bbf3c831 (diff)
microblaze: Highmem support
The first highmem implementation. Signed-off-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'arch/microblaze/mm')
-rw-r--r--arch/microblaze/mm/Makefile1
-rw-r--r--arch/microblaze/mm/highmem.c88
-rw-r--r--arch/microblaze/mm/init.c68
3 files changed, 157 insertions, 0 deletions
diff --git a/arch/microblaze/mm/Makefile b/arch/microblaze/mm/Makefile
index 09c49ed87235..7313bd8acbb7 100644
--- a/arch/microblaze/mm/Makefile
+++ b/arch/microblaze/mm/Makefile
@@ -5,3 +5,4 @@
5obj-y := consistent.o init.o 5obj-y := consistent.o init.o
6 6
7obj-$(CONFIG_MMU) += pgtable.o mmu_context.o fault.o 7obj-$(CONFIG_MMU) += pgtable.o mmu_context.o fault.o
8obj-$(CONFIG_HIGHMEM) += highmem.o
diff --git a/arch/microblaze/mm/highmem.c b/arch/microblaze/mm/highmem.c
new file mode 100644
index 000000000000..7d78838e8bfa
--- /dev/null
+++ b/arch/microblaze/mm/highmem.c
@@ -0,0 +1,88 @@
1/*
2 * highmem.c: virtual kernel memory mappings for high memory
3 *
4 * PowerPC version, stolen from the i386 version.
5 *
6 * Used in CONFIG_HIGHMEM systems for memory pages which
7 * are not addressable by direct kernel virtual addresses.
8 *
9 * Copyright (C) 1999 Gerhard Wichert, Siemens AG
10 * Gerhard.Wichert@pdb.siemens.de
11 *
12 *
13 * Redesigned the x86 32-bit VM architecture to deal with
14 * up to 16 Terrabyte physical memory. With current x86 CPUs
15 * we now support up to 64 Gigabytes physical RAM.
16 *
17 * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
18 *
19 * Reworked for PowerPC by various contributors. Moved from
20 * highmem.h by Benjamin Herrenschmidt (c) 2009 IBM Corp.
21 */
22
23#include <linux/highmem.h>
24#include <linux/module.h>
25
26/*
27 * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap
28 * gives a more generic (and caching) interface. But kmap_atomic can
29 * be used in IRQ contexts, so in some (very limited) cases we need
30 * it.
31 */
32#include <asm/tlbflush.h>
33
34void *kmap_atomic_prot(struct page *page, pgprot_t prot)
35{
36
37 unsigned long vaddr;
38 int idx, type;
39
40 /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
41 pagefault_disable();
42 if (!PageHighMem(page))
43 return page_address(page);
44
45
46 type = kmap_atomic_idx_push();
47 idx = type + KM_TYPE_NR*smp_processor_id();
48 vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
49#ifdef CONFIG_DEBUG_HIGHMEM
50 BUG_ON(!pte_none(*(kmap_pte-idx)));
51#endif
52 set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot));
53 local_flush_tlb_page(NULL, vaddr);
54
55 return (void *) vaddr;
56}
57EXPORT_SYMBOL(kmap_atomic_prot);
58
59void __kunmap_atomic(void *kvaddr)
60{
61 unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
62 int type;
63
64 if (vaddr < __fix_to_virt(FIX_KMAP_END)) {
65 pagefault_enable();
66 return;
67 }
68
69 type = kmap_atomic_idx();
70#ifdef CONFIG_DEBUG_HIGHMEM
71 {
72 unsigned int idx;
73
74 idx = type + KM_TYPE_NR * smp_processor_id();
75 BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
76
77 /*
78 * force other mappings to Oops if they'll try to access
79 * this pte without first remap it
80 */
81 pte_clear(&init_mm, vaddr, kmap_pte-idx);
82 local_flush_tlb_page(NULL, vaddr);
83 }
84#endif
85 kmap_atomic_idx_pop();
86 pagefault_enable();
87}
88EXPORT_SYMBOL(__kunmap_atomic);
diff --git a/arch/microblaze/mm/init.c b/arch/microblaze/mm/init.c
index 43b3f604bafe..95297b13dd9e 100644
--- a/arch/microblaze/mm/init.c
+++ b/arch/microblaze/mm/init.c
@@ -49,6 +49,53 @@ unsigned long memory_size;
49EXPORT_SYMBOL(memory_size); 49EXPORT_SYMBOL(memory_size);
50unsigned long lowmem_size; 50unsigned long lowmem_size;
51 51
52#ifdef CONFIG_HIGHMEM
53pte_t *kmap_pte;
54EXPORT_SYMBOL(kmap_pte);
55pgprot_t kmap_prot;
56EXPORT_SYMBOL(kmap_prot);
57
58static inline pte_t *virt_to_kpte(unsigned long vaddr)
59{
60 return pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr),
61 vaddr), vaddr);
62}
63
64static void __init highmem_init(void)
65{
66 pr_debug("%x\n", (u32)PKMAP_BASE);
67 map_page(PKMAP_BASE, 0, 0); /* XXX gross */
68 pkmap_page_table = virt_to_kpte(PKMAP_BASE);
69
70 kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN));
71 kmap_prot = PAGE_KERNEL;
72}
73
74static unsigned long highmem_setup(void)
75{
76 unsigned long pfn;
77 unsigned long reservedpages = 0;
78
79 for (pfn = max_low_pfn; pfn < max_pfn; ++pfn) {
80 struct page *page = pfn_to_page(pfn);
81
82 /* FIXME not sure about */
83 if (memblock_is_reserved(pfn << PAGE_SHIFT))
84 continue;
85 ClearPageReserved(page);
86 init_page_count(page);
87 __free_page(page);
88 totalhigh_pages++;
89 reservedpages++;
90 }
91 totalram_pages += totalhigh_pages;
92 printk(KERN_INFO "High memory: %luk\n",
93 totalhigh_pages << (PAGE_SHIFT-10));
94
95 return reservedpages;
96}
97#endif /* CONFIG_HIGHMEM */
98
52/* 99/*
53 * paging_init() sets up the page tables - in fact we've already done this. 100 * paging_init() sets up the page tables - in fact we've already done this.
54 */ 101 */
@@ -66,7 +113,14 @@ static void __init paging_init(void)
66 /* Clean every zones */ 113 /* Clean every zones */
67 memset(zones_size, 0, sizeof(zones_size)); 114 memset(zones_size, 0, sizeof(zones_size));
68 115
116#ifdef CONFIG_HIGHMEM
117 highmem_init();
118
119 zones_size[ZONE_DMA] = max_low_pfn;
120 zones_size[ZONE_HIGHMEM] = max_pfn;
121#else
69 zones_size[ZONE_DMA] = max_pfn; 122 zones_size[ZONE_DMA] = max_pfn;
123#endif
70 124
71 /* We don't have holes in memory map */ 125 /* We don't have holes in memory map */
72 free_area_init_nodes(zones_size); 126 free_area_init_nodes(zones_size);
@@ -241,6 +295,10 @@ void __init mem_init(void)
241 } 295 }
242 } 296 }
243 297
298#ifdef CONFIG_HIGHMEM
299 reservedpages -= highmem_setup();
300#endif
301
244 codesize = (unsigned long)&_sdata - (unsigned long)&_stext; 302 codesize = (unsigned long)&_sdata - (unsigned long)&_stext;
245 datasize = (unsigned long)&_edata - (unsigned long)&_sdata; 303 datasize = (unsigned long)&_edata - (unsigned long)&_sdata;
246 initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin; 304 initsize = (unsigned long)&__init_end - (unsigned long)&__init_begin;
@@ -259,6 +317,10 @@ void __init mem_init(void)
259#ifdef CONFIG_MMU 317#ifdef CONFIG_MMU
260 pr_info("Kernel virtual memory layout:\n"); 318 pr_info("Kernel virtual memory layout:\n");
261 pr_info(" * 0x%08lx..0x%08lx : fixmap\n", FIXADDR_START, FIXADDR_TOP); 319 pr_info(" * 0x%08lx..0x%08lx : fixmap\n", FIXADDR_START, FIXADDR_TOP);
320#ifdef CONFIG_HIGHMEM
321 pr_info(" * 0x%08lx..0x%08lx : highmem PTEs\n",
322 PKMAP_BASE, PKMAP_ADDR(LAST_PKMAP));
323#endif /* CONFIG_HIGHMEM */
262 pr_info(" * 0x%08lx..0x%08lx : early ioremap\n", 324 pr_info(" * 0x%08lx..0x%08lx : early ioremap\n",
263 ioremap_bot, ioremap_base); 325 ioremap_bot, ioremap_base);
264 pr_info(" * 0x%08lx..0x%08lx : vmalloc & ioremap\n", 326 pr_info(" * 0x%08lx..0x%08lx : vmalloc & ioremap\n",
@@ -346,7 +408,9 @@ asmlinkage void __init mmu_init(void)
346 408
347 if (lowmem_size > CONFIG_LOWMEM_SIZE) { 409 if (lowmem_size > CONFIG_LOWMEM_SIZE) {
348 lowmem_size = CONFIG_LOWMEM_SIZE; 410 lowmem_size = CONFIG_LOWMEM_SIZE;
411#ifndef CONFIG_HIGHMEM
349 memory_size = lowmem_size; 412 memory_size = lowmem_size;
413#endif
350 } 414 }
351 415
352 mm_cmdline_setup(); /* FIXME parse args from command line - not used */ 416 mm_cmdline_setup(); /* FIXME parse args from command line - not used */
@@ -375,7 +439,11 @@ asmlinkage void __init mmu_init(void)
375 mapin_ram(); 439 mapin_ram();
376 440
377 /* Extend vmalloc and ioremap area as big as possible */ 441 /* Extend vmalloc and ioremap area as big as possible */
442#ifdef CONFIG_HIGHMEM
443 ioremap_base = ioremap_bot = PKMAP_BASE;
444#else
378 ioremap_base = ioremap_bot = FIXADDR_START; 445 ioremap_base = ioremap_bot = FIXADDR_START;
446#endif
379 447
380 /* Initialize the context management stuff */ 448 /* Initialize the context management stuff */
381 mmu_context_init(); 449 mmu_context_init();