blob: bb9c98f9cb5b5845bf2caf87589902375a01289d [file] [log] [blame]
Bryan Wu1394f032007-05-06 14:50:22 -07001/*
Robin Getz96f10502009-09-24 14:11:24 +00002 * Copyright 2004-2009 Analog Devices Inc.
Bryan Wu1394f032007-05-06 14:50:22 -07003 *
Robin Getz96f10502009-09-24 14:11:24 +00004 * Licensed under the GPL-2 or later.
Bryan Wu1394f032007-05-06 14:50:22 -07005 */
6
7#include <linux/swap.h>
8#include <linux/bootmem.h>
Mike Frysinger1f83b8f2007-07-12 22:58:21 +08009#include <linux/uaccess.h>
Bryan Wu1394f032007-05-06 14:50:22 -070010#include <asm/bfin-global.h>
Graf Yang8f658732008-11-18 17:48:22 +080011#include <asm/pda.h>
12#include <asm/cplbinit.h>
Robin Getz837ec2d2009-07-07 20:17:09 +000013#include <asm/early_printk.h>
Bryan Wu1394f032007-05-06 14:50:22 -070014#include "blackfin_sram.h"
15
16/*
17 * BAD_PAGE is the page that is used for page faults when linux
18 * is out-of-memory. Older versions of linux just did a
19 * do_exit(), but using this instead means there is less risk
20 * for a process dying in kernel mode, possibly leaving a inode
21 * unused etc..
22 *
23 * BAD_PAGETABLE is the accompanying page-table: it is initialized
24 * to point to BAD_PAGE entries.
25 *
26 * ZERO_PAGE is a special page that is used for zero-initialized
27 * data and COW.
28 */
29static unsigned long empty_bad_page_table;
30
31static unsigned long empty_bad_page;
32
Graf Yangf82e0a02009-04-08 08:30:22 +000033static unsigned long empty_zero_page;
Bryan Wu1394f032007-05-06 14:50:22 -070034
Graf Yangf82e0a02009-04-08 08:30:22 +000035#ifndef CONFIG_EXCEPTION_L1_SCRATCH
36#if defined CONFIG_SYSCALL_TAB_L1
37__attribute__((l1_data))
38#endif
39static unsigned long exception_stack[NR_CPUS][1024];
40#endif
Graf Yang8f658732008-11-18 17:48:22 +080041
42struct blackfin_pda cpu_pda[NR_CPUS];
43EXPORT_SYMBOL(cpu_pda);
44
Bryan Wu1394f032007-05-06 14:50:22 -070045/*
46 * paging_init() continues the virtual memory environment setup which
47 * was begun by the code in arch/head.S.
48 * The parameters are pointers to where to stick the starting and ending
49 * addresses of available kernel virtual memory.
50 */
Mike Frysinger321f6e02007-06-11 15:31:30 +080051void __init paging_init(void)
Bryan Wu1394f032007-05-06 14:50:22 -070052{
53 /*
54 * make sure start_mem is page aligned, otherwise bootmem and
55 * page_alloc get different views og the world
56 */
57 unsigned long end_mem = memory_end & PAGE_MASK;
58
59 pr_debug("start_mem is %#lx virtual_end is %#lx\n", PAGE_ALIGN(memory_start), end_mem);
60
61 /*
62 * initialize the bad page table and bad page to point
63 * to a couple of allocated pages
64 */
65 empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
66 empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
67 empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
68 memset((void *)empty_zero_page, 0, PAGE_SIZE);
69
70 /*
71 * Set up SFC/DFC registers (user data space)
72 */
73 set_fs(KERNEL_DS);
74
75 pr_debug("free_area_init -> start_mem is %#lx virtual_end is %#lx\n",
76 PAGE_ALIGN(memory_start), end_mem);
77
78 {
79 unsigned long zones_size[MAX_NR_ZONES] = { 0, };
80
Aubrey Lie3defff2007-05-21 18:09:11 +080081 zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
82 zones_size[ZONE_NORMAL] = 0;
Bryan Wu1394f032007-05-06 14:50:22 -070083#ifdef CONFIG_HIGHMEM
84 zones_size[ZONE_HIGHMEM] = 0;
85#endif
86 free_area_init(zones_size);
87 }
88}
89
Mike Frysinger8e2a7692009-03-05 18:45:07 +080090asmlinkage void __init init_pda(void)
Graf Yang8f658732008-11-18 17:48:22 +080091{
92 unsigned int cpu = raw_smp_processor_id();
93
Robin Getz837ec2d2009-07-07 20:17:09 +000094 early_shadow_stamp();
95
Graf Yang8f658732008-11-18 17:48:22 +080096 /* Initialize the PDA fields holding references to other parts
97 of the memory. The content of such memory is still
98 undefined at the time of the call, we are only setting up
99 valid pointers to it. */
100 memset(&cpu_pda[cpu], 0, sizeof(cpu_pda[cpu]));
101
102 cpu_pda[0].next = &cpu_pda[1];
103 cpu_pda[1].next = &cpu_pda[0];
104
Graf Yangf82e0a02009-04-08 08:30:22 +0000105#ifdef CONFIG_EXCEPTION_L1_SCRATCH
106 cpu_pda[cpu].ex_stack = (unsigned long *)(L1_SCRATCH_START + \
107 L1_SCRATCH_LENGTH);
108#else
Graf Yang8f658732008-11-18 17:48:22 +0800109 cpu_pda[cpu].ex_stack = exception_stack[cpu + 1];
Graf Yangf82e0a02009-04-08 08:30:22 +0000110#endif
Graf Yang8f658732008-11-18 17:48:22 +0800111
Graf Yang8f658732008-11-18 17:48:22 +0800112#ifdef CONFIG_SMP
113 cpu_pda[cpu].imask = 0x1f;
114#endif
115}
116
Mike Frysinger321f6e02007-06-11 15:31:30 +0800117void __init mem_init(void)
Bryan Wu1394f032007-05-06 14:50:22 -0700118{
119 unsigned int codek = 0, datak = 0, initk = 0;
Yi Liee7883b2008-01-27 19:56:17 +0800120 unsigned int reservedpages = 0, freepages = 0;
Bryan Wu1394f032007-05-06 14:50:22 -0700121 unsigned long tmp;
Bryan Wu1394f032007-05-06 14:50:22 -0700122 unsigned long start_mem = memory_start;
123 unsigned long end_mem = memory_end;
124
125 end_mem &= PAGE_MASK;
126 high_memory = (void *)end_mem;
127
128 start_mem = PAGE_ALIGN(start_mem);
129 max_mapnr = num_physpages = MAP_NR(high_memory);
Yi Li856783b2008-02-09 02:26:01 +0800130 printk(KERN_DEBUG "Kernel managed physical pages: %lu\n", num_physpages);
Bryan Wu1394f032007-05-06 14:50:22 -0700131
132 /* This will put all memory onto the freelists. */
133 totalram_pages = free_all_bootmem();
134
Yi Liee7883b2008-01-27 19:56:17 +0800135 reservedpages = 0;
136 for (tmp = 0; tmp < max_mapnr; tmp++)
137 if (PageReserved(pfn_to_page(tmp)))
138 reservedpages++;
139 freepages = max_mapnr - reservedpages;
Bryan Wu1394f032007-05-06 14:50:22 -0700140
Yi Liee7883b2008-01-27 19:56:17 +0800141 /* do not count in kernel image between _rambase and _ramstart */
142 reservedpages -= (_ramstart - _rambase) >> PAGE_SHIFT;
Jie Zhang41ba6532009-06-16 09:48:33 +0000143#if (defined(CONFIG_BFIN_EXTMEM_ICACHEABLE) && ANOMALY_05000263)
Yi Li856783b2008-02-09 02:26:01 +0800144 reservedpages += (_ramend - memory_end - DMA_UNCACHED_REGION) >> PAGE_SHIFT;
Yi Liee7883b2008-01-27 19:56:17 +0800145#endif
146
147 codek = (_etext - _stext) >> 10;
148 initk = (__init_end - __init_begin) >> 10;
149 datak = ((_ramstart - _rambase) >> 10) - codek - initk;
150
Bryan Wu1394f032007-05-06 14:50:22 -0700151 printk(KERN_INFO
Yi Liee7883b2008-01-27 19:56:17 +0800152 "Memory available: %luk/%luk RAM, "
Yi Li856783b2008-02-09 02:26:01 +0800153 "(%uk init code, %uk kernel code, %uk data, %uk dma, %uk reserved)\n",
Yi Liee7883b2008-01-27 19:56:17 +0800154 (unsigned long) freepages << (PAGE_SHIFT-10), _ramend >> 10,
Yi Li856783b2008-02-09 02:26:01 +0800155 initk, codek, datak, DMA_UNCACHED_REGION >> 10, (reservedpages << (PAGE_SHIFT-10)));
Sonic Zhang5d481f42008-07-19 14:51:31 +0800156}
157
Bryan Wuc0514892008-02-29 12:02:10 +0800158static void __init free_init_pages(const char *what, unsigned long begin, unsigned long end)
Mike Frysinger1d189472007-07-12 12:32:00 +0800159{
160 unsigned long addr;
161 /* next to check that the page we free is not a partial page */
162 for (addr = begin; addr + PAGE_SIZE <= end; addr += PAGE_SIZE) {
163 ClearPageReserved(virt_to_page(addr));
164 init_page_count(virt_to_page(addr));
165 free_page(addr);
166 totalram_pages++;
167 }
168 printk(KERN_INFO "Freeing %s: %ldk freed\n", what, (end - begin) >> 10);
169}
170
Bryan Wu1394f032007-05-06 14:50:22 -0700171#ifdef CONFIG_BLK_DEV_INITRD
Mike Frysinger321f6e02007-06-11 15:31:30 +0800172void __init free_initrd_mem(unsigned long start, unsigned long end)
Bryan Wu1394f032007-05-06 14:50:22 -0700173{
Bernd Schmidtb97b8a92008-01-27 18:39:16 +0800174#ifndef CONFIG_MPU
Mike Frysinger1d189472007-07-12 12:32:00 +0800175 free_init_pages("initrd memory", start, end);
Bernd Schmidtb97b8a92008-01-27 18:39:16 +0800176#endif
Bryan Wu1394f032007-05-06 14:50:22 -0700177}
178#endif
179
Bryan Wuc0514892008-02-29 12:02:10 +0800180void __init_refok free_initmem(void)
Bryan Wu1394f032007-05-06 14:50:22 -0700181{
Bernd Schmidtb97b8a92008-01-27 18:39:16 +0800182#if defined CONFIG_RAMKERNEL && !defined CONFIG_MPU
Mike Frysinger1d189472007-07-12 12:32:00 +0800183 free_init_pages("unused kernel memory",
184 (unsigned long)(&__init_begin),
185 (unsigned long)(&__init_end));
Bryan Wu1394f032007-05-06 14:50:22 -0700186#endif
187}