Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
openrisc
mm
init.c
Go to the documentation of this file.
1
/*
2
* OpenRISC idle.c
3
*
4
* Linux architectural port borrowing liberally from similar works of
5
* others. All original copyrights apply as per the original source
6
* declaration.
7
*
8
* Modifications for the OpenRISC architecture:
9
* Copyright (C) 2003 Matjaz Breskvar <
[email protected]
>
10
* Copyright (C) 2010-2011 Jonas Bonn <
[email protected]
>
11
*
12
* This program is free software; you can redistribute it and/or
13
* modify it under the terms of the GNU General Public License
14
* as published by the Free Software Foundation; either version
15
* 2 of the License, or (at your option) any later version.
16
*/
17
18
#include <linux/signal.h>
19
#include <linux/sched.h>
20
#include <linux/kernel.h>
21
#include <linux/errno.h>
22
#include <linux/string.h>
23
#include <linux/types.h>
24
#include <linux/ptrace.h>
25
#include <linux/mman.h>
26
#include <
linux/mm.h
>
27
#include <
linux/swap.h
>
28
#include <
linux/smp.h
>
29
#include <
linux/bootmem.h
>
30
#include <
linux/init.h
>
31
#include <
linux/delay.h
>
32
#include <
linux/blkdev.h
>
/* for initrd_* */
33
#include <
linux/pagemap.h
>
34
#include <
linux/memblock.h
>
35
36
#include <asm/segment.h>
37
#include <asm/pgalloc.h>
38
#include <asm/pgtable.h>
39
#include <asm/dma.h>
40
#include <asm/io.h>
41
#include <asm/tlb.h>
42
#include <asm/mmu_context.h>
43
#include <asm/kmap_types.h>
44
#include <asm/fixmap.h>
45
#include <asm/tlbflush.h>
46
47
int
mem_init_done
;
48
49
DEFINE_PER_CPU
(
struct
mmu_gather
, mmu_gathers);
50
51
static
void
__init
zone_sizes_init
(
void
)
52
{
53
unsigned
long
zones_size[MAX_NR_ZONES];
54
55
/* Clear the zone sizes */
56
memset
(zones_size, 0,
sizeof
(zones_size));
57
58
/*
59
* We use only ZONE_NORMAL
60
*/
61
zones_size[
ZONE_NORMAL
] =
max_low_pfn
;
62
63
free_area_init
(zones_size);
64
}
65
66
extern
const
char
_s_kernel_ro
[],
_e_kernel_ro
[];
67
68
/*
69
* Map all physical memory into kernel's address space.
70
*
71
* This is explicitly coded for two-level page tables, so if you need
72
* something else then this needs to change.
73
*/
74
static
void
__init
map_ram(
void
)
75
{
76
unsigned
long
v
,
p
,
e
;
77
pgprot_t
prot;
78
pgd_t
*pge;
79
pud_t
*pue;
80
pmd_t
*pme;
81
pte_t
*
pte
;
82
/* These mark extents of read-only kernel pages...
83
* ...from vmlinux.lds.S
84
*/
85
struct
memblock_region *
region
;
86
87
v =
PAGE_OFFSET
;
88
89
for_each_memblock(
memory
, region) {
90
p = (
u32
) region->base &
PAGE_MASK
;
91
e = p + (
u32
) region->size;
92
93
v = (
u32
)
__va
(p);
94
pge =
pgd_offset_k
(v);
95
96
while
(p < e) {
97
int
j
;
98
pue =
pud_offset
(pge, v);
99
pme =
pmd_offset
(pue, v);
100
101
if
((
u32
) pue != (
u32
) pge || (
u32
) pme != (
u32
) pge) {
102
panic
(
"%s: OR1K kernel hardcoded for "
103
"two-level page tables"
,
104
__func__);
105
}
106
107
/* Alloc one page for holding PTE's... */
108
pte = (
pte_t
*)
alloc_bootmem_low_pages
(
PAGE_SIZE
);
109
set_pmd
(pme,
__pmd
(
_KERNPG_TABLE
+
__pa
(pte)));
110
111
/* Fill the newly allocated page with PTE'S */
112
for
(j = 0; p < e && j <
PTRS_PER_PGD
;
113
v +=
PAGE_SIZE
, p +=
PAGE_SIZE
, j++, pte++) {
114
if
(v >= (
u32
) _e_kernel_ro ||
115
v < (
u32
) _s_kernel_ro)
116
prot =
PAGE_KERNEL
;
117
else
118
prot =
PAGE_KERNEL_RO
;
119
120
set_pte
(pte,
mk_pte_phys
(p, prot));
121
}
122
123
pge++;
124
}
125
126
printk
(
KERN_INFO
"%s: Memory: 0x%x-0x%x\n"
, __func__,
127
region->base, region->base + region->size);
128
}
129
}
130
131
void
__init
paging_init
(
void
)
132
{
133
extern
void
tlb_init
(
void
);
134
135
unsigned
long
end
;
136
int
i
;
137
138
printk
(
KERN_INFO
"Setting up paging and PTEs.\n"
);
139
140
/* clear out the init_mm.pgd that will contain the kernel's mappings */
141
142
for
(i = 0; i <
PTRS_PER_PGD
; i++)
143
swapper_pg_dir
[i] =
__pgd
(0);
144
145
/* make sure the current pgd table points to something sane
146
* (even if it is most probably not used until the next
147
* switch_mm)
148
*/
149
current_pgd
=
init_mm
.pgd;
150
151
end = (
unsigned
long
)
__va
(
max_low_pfn
*
PAGE_SIZE
);
152
153
map_ram();
154
155
zone_sizes_init
();
156
157
/* self modifying code ;) */
158
/* Since the old TLB miss handler has been running up until now,
159
* the kernel pages are still all RW, so we can still modify the
160
* text directly... after this change and a TLB flush, the kernel
161
* pages will become RO.
162
*/
163
{
164
extern
unsigned
long
dtlb_miss_handler;
165
extern
unsigned
long
itlb_miss_handler;
166
167
unsigned
long
*dtlb_vector =
__va
(0x900);
168
unsigned
long
*itlb_vector =
__va
(0xa00);
169
170
printk
(
KERN_INFO
"dtlb_miss_handler %p\n"
, &dtlb_miss_handler);
171
*dtlb_vector = ((
unsigned
long
)&dtlb_miss_handler -
172
(
unsigned
long
)dtlb_vector) >> 2;
173
174
printk
(
KERN_INFO
"itlb_miss_handler %p\n"
, &itlb_miss_handler);
175
*itlb_vector = ((
unsigned
long
)&itlb_miss_handler -
176
(
unsigned
long
)itlb_vector) >> 2;
177
}
178
179
/* Invalidate instruction caches after code modification */
180
mtspr
(
SPR_ICBIR
, 0x900);
181
mtspr
(
SPR_ICBIR
, 0xa00);
182
183
/* New TLB miss handlers and kernel page tables are in now place.
184
* Make sure that page flags get updated for all pages in TLB by
185
* flushing the TLB and forcing all TLB entries to be recreated
186
* from their page table flags.
187
*/
188
flush_tlb_all
();
189
}
190
191
/* References to section boundaries */
192
193
extern
char
_stext
,
_etext
,
_edata
,
__bss_start
,
_end
;
194
extern
char
__init_begin
,
__init_end
;
195
196
static
int
__init
free_pages_init(
void
)
197
{
198
int
reservedpages, pfn;
199
200
/* this will put all low memory onto the freelists */
201
totalram_pages =
free_all_bootmem
();
202
203
reservedpages = 0;
204
for
(pfn = 0; pfn <
max_low_pfn
; pfn++) {
205
/*
206
* Only count reserved RAM pages
207
*/
208
if
(PageReserved(
mem_map
+ pfn))
209
reservedpages++;
210
}
211
212
return
reservedpages;
213
}
214
215
static
void
__init
set_max_mapnr_init(
void
)
216
{
217
max_mapnr
=
num_physpages
=
max_low_pfn
;
218
}
219
220
void
__init
mem_init
(
void
)
221
{
222
int
codesize, reservedpages, datasize, initsize;
223
224
BUG_ON
(!
mem_map
);
225
226
set_max_mapnr_init();
227
228
high_memory
= (
void
*)
__va
(max_low_pfn *
PAGE_SIZE
);
229
230
/* clear the zero-page */
231
memset
((
void
*)
empty_zero_page
, 0, PAGE_SIZE);
232
233
reservedpages = free_pages_init();
234
235
codesize = (
unsigned
long
)&_etext - (
unsigned
long
)&_stext;
236
datasize = (
unsigned
long
)&_edata - (
unsigned
long
)&_etext;
237
initsize = (
unsigned
long
)&__init_end - (
unsigned
long
)&__init_begin;
238
239
printk
(
KERN_INFO
240
"Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n"
,
241
(
unsigned
long
)nr_free_pages() << (
PAGE_SHIFT
- 10),
242
max_mapnr
<< (
PAGE_SHIFT
- 10), codesize >> 10,
243
reservedpages << (
PAGE_SHIFT
- 10), datasize >> 10,
244
initsize >> 10, (
unsigned
long
)(0 << (
PAGE_SHIFT
- 10))
245
);
246
247
printk
(
"mem_init_done ...........................................\n"
);
248
mem_init_done
= 1;
249
return
;
250
}
251
252
#ifdef CONFIG_BLK_DEV_INITRD
253
void
free_initrd_mem
(
unsigned
long
start
,
unsigned
long
end
)
254
{
255
printk
(
KERN_INFO
"Freeing initrd memory: %ldk freed\n"
,
256
(end - start) >> 10);
257
258
for
(; start <
end
; start +=
PAGE_SIZE
) {
259
ClearPageReserved(
virt_to_page
(start));
260
init_page_count(
virt_to_page
(start));
261
free_page
(start);
262
totalram_pages++;
263
}
264
}
265
#endif
266
267
void
free_initmem
(
void
)
268
{
269
unsigned
long
addr
;
270
271
addr = (
unsigned
long
)(&__init_begin);
272
for
(; addr < (
unsigned
long
)(&__init_end); addr +=
PAGE_SIZE
) {
273
ClearPageReserved(
virt_to_page
(addr));
274
init_page_count(
virt_to_page
(addr));
275
free_page
(addr);
276
totalram_pages++;
277
}
278
printk
(
KERN_INFO
"Freeing unused kernel memory: %luk freed\n"
,
279
((
unsigned
long
)&__init_end -
280
(
unsigned
long
)&__init_begin) >> 10);
281
}
Generated on Thu Jan 10 2013 12:54:02 for Linux Kernel by
1.8.2