Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/sparc/mm/init_32.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* linux/arch/sparc/mm/init.c
4
*
5
* Copyright (C) 1995 David S. Miller ([email protected])
6
* Copyright (C) 1995 Eddie C. Dost ([email protected])
7
* Copyright (C) 1998 Jakub Jelinek ([email protected])
8
* Copyright (C) 2000 Anton Blanchard ([email protected])
9
*/
10
11
#include <linux/module.h>
12
#include <linux/signal.h>
13
#include <linux/sched.h>
14
#include <linux/kernel.h>
15
#include <linux/errno.h>
16
#include <linux/string.h>
17
#include <linux/types.h>
18
#include <linux/ptrace.h>
19
#include <linux/mman.h>
20
#include <linux/mm.h>
21
#include <linux/swap.h>
22
#include <linux/initrd.h>
23
#include <linux/init.h>
24
#include <linux/highmem.h>
25
#include <linux/memblock.h>
26
#include <linux/pagemap.h>
27
#include <linux/poison.h>
28
#include <linux/gfp.h>
29
30
#include <asm/sections.h>
31
#include <asm/page.h>
32
#include <asm/vaddrs.h>
33
#include <asm/setup.h>
34
#include <asm/tlb.h>
35
#include <asm/prom.h>
36
#include <asm/leon.h>
37
38
#include "mm_32.h"
39
40
static unsigned long *sparc_valid_addr_bitmap;
41
42
unsigned long phys_base;
43
EXPORT_SYMBOL(phys_base);
44
45
unsigned long pfn_base;
46
EXPORT_SYMBOL(pfn_base);
47
48
struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1];
49
50
/* Initial ramdisk setup */
51
extern unsigned int sparc_ramdisk_image;
52
extern unsigned int sparc_ramdisk_size;
53
54
unsigned long highstart_pfn, highend_pfn;
55
56
unsigned long last_valid_pfn;
57
58
unsigned long calc_highpages(void)
59
{
60
int i;
61
int nr = 0;
62
63
for (i = 0; sp_banks[i].num_bytes != 0; i++) {
64
unsigned long start_pfn = sp_banks[i].base_addr >> PAGE_SHIFT;
65
unsigned long end_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT;
66
67
if (end_pfn <= max_low_pfn)
68
continue;
69
70
if (start_pfn < max_low_pfn)
71
start_pfn = max_low_pfn;
72
73
nr += end_pfn - start_pfn;
74
}
75
76
return nr;
77
}
78
79
static unsigned long calc_max_low_pfn(void)
80
{
81
int i;
82
unsigned long tmp = pfn_base + (SRMMU_MAXMEM >> PAGE_SHIFT);
83
unsigned long curr_pfn, last_pfn;
84
85
last_pfn = (sp_banks[0].base_addr + sp_banks[0].num_bytes) >> PAGE_SHIFT;
86
for (i = 1; sp_banks[i].num_bytes != 0; i++) {
87
curr_pfn = sp_banks[i].base_addr >> PAGE_SHIFT;
88
89
if (curr_pfn >= tmp) {
90
if (last_pfn < tmp)
91
tmp = last_pfn;
92
break;
93
}
94
95
last_pfn = (sp_banks[i].base_addr + sp_banks[i].num_bytes) >> PAGE_SHIFT;
96
}
97
98
return tmp;
99
}
100
101
static void __init find_ramdisk(unsigned long end_of_phys_memory)
102
{
103
#ifdef CONFIG_BLK_DEV_INITRD
104
unsigned long size;
105
106
/* Now have to check initial ramdisk, so that it won't pass
107
* the end of memory
108
*/
109
if (sparc_ramdisk_image) {
110
if (sparc_ramdisk_image >= (unsigned long)&_end - 2 * PAGE_SIZE)
111
sparc_ramdisk_image -= KERNBASE;
112
initrd_start = sparc_ramdisk_image + phys_base;
113
initrd_end = initrd_start + sparc_ramdisk_size;
114
if (initrd_end > end_of_phys_memory) {
115
printk(KERN_CRIT "initrd extends beyond end of memory "
116
"(0x%016lx > 0x%016lx)\ndisabling initrd\n",
117
initrd_end, end_of_phys_memory);
118
initrd_start = 0;
119
} else {
120
/* Reserve the initrd image area. */
121
size = initrd_end - initrd_start;
122
memblock_reserve(initrd_start, size);
123
124
initrd_start = (initrd_start - phys_base) + PAGE_OFFSET;
125
initrd_end = (initrd_end - phys_base) + PAGE_OFFSET;
126
}
127
}
128
#endif
129
}
130
131
unsigned long __init bootmem_init(unsigned long *pages_avail)
132
{
133
unsigned long start_pfn, bytes_avail, size;
134
unsigned long end_of_phys_memory = 0;
135
unsigned long high_pages = 0;
136
int i;
137
138
memblock_set_bottom_up(true);
139
memblock_allow_resize();
140
141
bytes_avail = 0UL;
142
for (i = 0; sp_banks[i].num_bytes != 0; i++) {
143
end_of_phys_memory = sp_banks[i].base_addr +
144
sp_banks[i].num_bytes;
145
bytes_avail += sp_banks[i].num_bytes;
146
if (cmdline_memory_size) {
147
if (bytes_avail > cmdline_memory_size) {
148
unsigned long slack = bytes_avail - cmdline_memory_size;
149
150
bytes_avail -= slack;
151
end_of_phys_memory -= slack;
152
153
sp_banks[i].num_bytes -= slack;
154
if (sp_banks[i].num_bytes == 0) {
155
sp_banks[i].base_addr = 0xdeadbeef;
156
} else {
157
memblock_add(sp_banks[i].base_addr,
158
sp_banks[i].num_bytes);
159
sp_banks[i+1].num_bytes = 0;
160
sp_banks[i+1].base_addr = 0xdeadbeef;
161
}
162
break;
163
}
164
}
165
memblock_add(sp_banks[i].base_addr, sp_banks[i].num_bytes);
166
}
167
168
/* Start with page aligned address of last symbol in kernel
169
* image.
170
*/
171
start_pfn = (unsigned long)__pa(PAGE_ALIGN((unsigned long) &_end));
172
173
/* Now shift down to get the real physical page frame number. */
174
start_pfn >>= PAGE_SHIFT;
175
176
max_pfn = end_of_phys_memory >> PAGE_SHIFT;
177
178
max_low_pfn = max_pfn;
179
highstart_pfn = highend_pfn = max_pfn;
180
181
if (max_low_pfn > pfn_base + (SRMMU_MAXMEM >> PAGE_SHIFT)) {
182
highstart_pfn = pfn_base + (SRMMU_MAXMEM >> PAGE_SHIFT);
183
max_low_pfn = calc_max_low_pfn();
184
high_pages = calc_highpages();
185
printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
186
high_pages >> (20 - PAGE_SHIFT));
187
}
188
189
find_ramdisk(end_of_phys_memory);
190
191
/* Reserve the kernel text/data/bss. */
192
size = (start_pfn << PAGE_SHIFT) - phys_base;
193
memblock_reserve(phys_base, size);
194
memblock_add(phys_base, size);
195
196
size = memblock_phys_mem_size() - memblock_reserved_size();
197
*pages_avail = (size >> PAGE_SHIFT) - high_pages;
198
199
/* Only allow low memory to be allocated via memblock allocation */
200
memblock_set_current_limit(max_low_pfn << PAGE_SHIFT);
201
202
return max_pfn;
203
}
204
205
/*
206
* paging_init() sets up the page tables: We call the MMU specific
207
* init routine based upon the Sun model type on the Sparc.
208
*
209
*/
210
void __init paging_init(void)
211
{
212
srmmu_paging_init();
213
prom_build_devicetree();
214
of_fill_in_cpu_data();
215
device_scan();
216
}
217
218
static void __init taint_real_pages(void)
219
{
220
int i;
221
222
for (i = 0; sp_banks[i].num_bytes; i++) {
223
unsigned long start, end;
224
225
start = sp_banks[i].base_addr;
226
end = start + sp_banks[i].num_bytes;
227
228
while (start < end) {
229
set_bit(start >> 20, sparc_valid_addr_bitmap);
230
start += PAGE_SIZE;
231
}
232
}
233
}
234
235
void __init arch_mm_preinit(void)
236
{
237
int i;
238
239
if (PKMAP_BASE+LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) {
240
prom_printf("BUG: fixmap and pkmap areas overlap\n");
241
prom_printf("pkbase: 0x%lx pkend: 0x%lx fixstart 0x%lx\n",
242
PKMAP_BASE,
243
(unsigned long)PKMAP_BASE+LAST_PKMAP*PAGE_SIZE,
244
FIXADDR_START);
245
prom_printf("Please mail [email protected].\n");
246
prom_halt();
247
}
248
249
250
/* Saves us work later. */
251
memset((void *)empty_zero_page, 0, PAGE_SIZE);
252
253
i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5);
254
i += 1;
255
sparc_valid_addr_bitmap = (unsigned long *)
256
memblock_alloc(i << 2, SMP_CACHE_BYTES);
257
258
if (sparc_valid_addr_bitmap == NULL) {
259
prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
260
prom_halt();
261
}
262
memset(sparc_valid_addr_bitmap, 0, i << 2);
263
264
taint_real_pages();
265
}
266
267
void sparc_flush_page_to_ram(struct page *page)
268
{
269
unsigned long vaddr = (unsigned long)page_address(page);
270
271
__flush_page_to_ram(vaddr);
272
}
273
EXPORT_SYMBOL(sparc_flush_page_to_ram);
274
275
void sparc_flush_folio_to_ram(struct folio *folio)
276
{
277
unsigned long vaddr = (unsigned long)folio_address(folio);
278
unsigned int i, nr = folio_nr_pages(folio);
279
280
for (i = 0; i < nr; i++)
281
__flush_page_to_ram(vaddr + i * PAGE_SIZE);
282
}
283
EXPORT_SYMBOL(sparc_flush_folio_to_ram);
284
285
static const pgprot_t protection_map[16] = {
286
[VM_NONE] = PAGE_NONE,
287
[VM_READ] = PAGE_READONLY,
288
[VM_WRITE] = PAGE_COPY,
289
[VM_WRITE | VM_READ] = PAGE_COPY,
290
[VM_EXEC] = PAGE_READONLY,
291
[VM_EXEC | VM_READ] = PAGE_READONLY,
292
[VM_EXEC | VM_WRITE] = PAGE_COPY,
293
[VM_EXEC | VM_WRITE | VM_READ] = PAGE_COPY,
294
[VM_SHARED] = PAGE_NONE,
295
[VM_SHARED | VM_READ] = PAGE_READONLY,
296
[VM_SHARED | VM_WRITE] = PAGE_SHARED,
297
[VM_SHARED | VM_WRITE | VM_READ] = PAGE_SHARED,
298
[VM_SHARED | VM_EXEC] = PAGE_READONLY,
299
[VM_SHARED | VM_EXEC | VM_READ] = PAGE_READONLY,
300
[VM_SHARED | VM_EXEC | VM_WRITE] = PAGE_SHARED,
301
[VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = PAGE_SHARED
302
};
303
DECLARE_VM_GET_PAGE_PROT
304
305