OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [m68k/] [mm/] [motorola.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * linux/arch/m68k/motorola.c
3
 *
4
 * Routines specific to the Motorola MMU, originally from:
5
 * linux/arch/m68k/init.c
6
 * which are Copyright (C) 1995 Hamish Macdonald
7
 *
8
 * Moved 8/20/1999 Sam Creasey
9
 */
10
 
11
#include <linux/config.h>
12
#include <linux/signal.h>
13
#include <linux/sched.h>
14
#include <linux/mm.h>
15
#include <linux/swap.h>
16
#include <linux/kernel.h>
17
#include <linux/string.h>
18
#include <linux/types.h>
19
#include <linux/init.h>
20
#include <linux/bootmem.h>
21
#ifdef CONFIG_BLK_DEV_RAM
22
#include <linux/blk.h>
23
#endif
24
 
25
#include <asm/setup.h>
26
#include <asm/uaccess.h>
27
#include <asm/page.h>
28
#include <asm/pgalloc.h>
29
#include <asm/system.h>
30
#include <asm/machdep.h>
31
#include <asm/io.h>
32
#include <asm/dma.h>
33
#ifdef CONFIG_ATARI
34
#include <asm/atari_stram.h>
35
#endif
36
 
37
#undef DEBUG
38
 
39
#ifndef mm_cachebits
40
/*
41
 * Bits to add to page descriptors for "normal" caching mode.
42
 * For 68020/030 this is 0.
43
 * For 68040, this is _PAGE_CACHE040 (cachable, copyback)
44
 */
45
unsigned long mm_cachebits = 0;
46
#endif
47
 
48
static pte_t * __init kernel_page_table(void)
49
{
50
        pte_t *ptablep;
51
 
52
        ptablep = (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
53
 
54
        clear_page(ptablep);
55
        __flush_page_to_ram((unsigned long) ptablep);
56
        flush_tlb_kernel_page((unsigned long) ptablep);
57
        nocache_page ((unsigned long)ptablep);
58
 
59
        return ptablep;
60
}
61
 
62
static pmd_t *last_pgtable __initdata = NULL;
63
pmd_t *zero_pgtable __initdata = NULL;
64
 
65
static pmd_t * __init kernel_ptr_table(void)
66
{
67
        if (!last_pgtable) {
68
                unsigned long pmd, last;
69
                int i;
70
 
71
                /* Find the last ptr table that was used in head.S and
72
                 * reuse the remaining space in that page for further
73
                 * ptr tables.
74
                 */
75
                last = (unsigned long)kernel_pg_dir;
76
                for (i = 0; i < PTRS_PER_PGD; i++) {
77
                        if (!pgd_present(kernel_pg_dir[i]))
78
                                continue;
79
                        pmd = __pgd_page(kernel_pg_dir[i]);
80
                        if (pmd > last)
81
                                last = pmd;
82
                }
83
 
84
                last_pgtable = (pmd_t *)last;
85
#ifdef DEBUG
86
                printk("kernel_ptr_init: %p\n", last_pgtable);
87
#endif
88
        }
89
 
90
        if (((unsigned long)(last_pgtable + PTRS_PER_PMD) & ~PAGE_MASK) == 0) {
91
                last_pgtable = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
92
 
93
                clear_page(last_pgtable);
94
                __flush_page_to_ram((unsigned long)last_pgtable);
95
                flush_tlb_kernel_page((unsigned long)last_pgtable);
96
                nocache_page((unsigned long)last_pgtable);
97
        } else
98
                last_pgtable += PTRS_PER_PMD;
99
 
100
        return last_pgtable;
101
}
102
 
103
static unsigned long __init
104
map_chunk (unsigned long addr, long size)
105
{
106
#define PTRTREESIZE (256*1024)
107
#define ROOTTREESIZE (32*1024*1024)
108
        static unsigned long virtaddr = PAGE_OFFSET;
109
        unsigned long physaddr;
110
        pgd_t *pgd_dir;
111
        pmd_t *pmd_dir;
112
        pte_t *pte_dir;
113
 
114
        physaddr = (addr | m68k_supervisor_cachemode |
115
                    _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
116
        if (CPU_IS_040_OR_060)
117
                physaddr |= _PAGE_GLOBAL040;
118
 
119
        while (size > 0) {
120
#ifdef DEBUG
121
                if (!(virtaddr & (PTRTREESIZE-1)))
122
                        printk ("\npa=%#lx va=%#lx ", physaddr & PAGE_MASK,
123
                                virtaddr);
124
#endif
125
                pgd_dir = pgd_offset_k(virtaddr);
126
                if (virtaddr && CPU_IS_020_OR_030) {
127
                        if (!(virtaddr & (ROOTTREESIZE-1)) &&
128
                            size >= ROOTTREESIZE) {
129
#ifdef DEBUG
130
                                printk ("[very early term]");
131
#endif
132
                                pgd_val(*pgd_dir) = physaddr;
133
                                size -= ROOTTREESIZE;
134
                                virtaddr += ROOTTREESIZE;
135
                                physaddr += ROOTTREESIZE;
136
                                continue;
137
                        }
138
                }
139
                if (!pgd_present(*pgd_dir)) {
140
                        pmd_dir = kernel_ptr_table();
141
#ifdef DEBUG
142
                        printk ("[new pointer %p]", pmd_dir);
143
#endif
144
                        pgd_set(pgd_dir, pmd_dir);
145
                } else
146
                        pmd_dir = pmd_offset(pgd_dir, virtaddr);
147
 
148
                if (CPU_IS_020_OR_030) {
149
                        if (virtaddr) {
150
#ifdef DEBUG
151
                                printk ("[early term]");
152
#endif
153
                                pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
154
                                physaddr += PTRTREESIZE;
155
                        } else {
156
                                int i;
157
#ifdef DEBUG
158
                                printk ("[zero map]");
159
#endif
160
                                zero_pgtable = kernel_ptr_table();
161
                                pte_dir = (pte_t *)zero_pgtable;
162
                                pmd_dir->pmd[0] = virt_to_phys(pte_dir) |
163
                                        _PAGE_TABLE | _PAGE_ACCESSED;
164
                                pte_val(*pte_dir++) = 0;
165
                                physaddr += PAGE_SIZE;
166
                                for (i = 1; i < 64; physaddr += PAGE_SIZE, i++)
167
                                        pte_val(*pte_dir++) = physaddr;
168
                        }
169
                        size -= PTRTREESIZE;
170
                        virtaddr += PTRTREESIZE;
171
                } else {
172
                        if (!pmd_present(*pmd_dir)) {
173
#ifdef DEBUG
174
                                printk ("[new table]");
175
#endif
176
                                pte_dir = kernel_page_table();
177
                                pmd_set(pmd_dir, pte_dir);
178
                        }
179
                        pte_dir = pte_offset(pmd_dir, virtaddr);
180
 
181
                        if (virtaddr) {
182
                                if (!pte_present(*pte_dir))
183
                                        pte_val(*pte_dir) = physaddr;
184
                        } else
185
                                pte_val(*pte_dir) = 0;
186
                        size -= PAGE_SIZE;
187
                        virtaddr += PAGE_SIZE;
188
                        physaddr += PAGE_SIZE;
189
                }
190
 
191
        }
192
#ifdef DEBUG
193
        printk("\n");
194
#endif
195
 
196
        return virtaddr;
197
}
198
 
199
extern unsigned long empty_bad_page_table;
200
extern unsigned long empty_bad_page;
201
 
202
/*
203
 * paging_init() continues the virtual memory environment setup which
204
 * was begun by the code in arch/head.S.
205
 */
206
void __init paging_init(void)
207
{
208
        int chunk;
209
        unsigned long mem_avail = 0;
210
        unsigned long zones_size[3] = { 0, };
211
 
212
#ifdef DEBUG
213
        {
214
                extern unsigned long availmem;
215
                printk ("start of paging_init (%p, %lx, %lx, %lx)\n",
216
                        kernel_pg_dir, availmem, start_mem, end_mem);
217
        }
218
#endif
219
 
220
        /* Fix the cache mode in the page descriptors for the 680[46]0.  */
221
        if (CPU_IS_040_OR_060) {
222
                int i;
223
#ifndef mm_cachebits
224
                mm_cachebits = _PAGE_CACHE040;
225
#endif
226
                for (i = 0; i < 16; i++)
227
                        pgprot_val(protection_map[i]) |= _PAGE_CACHE040;
228
        }
229
 
230
        /*
231
         * Map the physical memory available into the kernel virtual
232
         * address space.  It may allocate some memory for page
233
         * tables and thus modify availmem.
234
         */
235
 
236
        for (chunk = 0; chunk < m68k_num_memory; chunk++) {
237
                mem_avail = map_chunk (m68k_memory[chunk].addr,
238
                                       m68k_memory[chunk].size);
239
 
240
        }
241
 
242
        flush_tlb_all();
243
#ifdef DEBUG
244
        printk ("memory available is %ldKB\n", mem_avail >> 10);
245
        printk ("start_mem is %#lx\nvirtual_end is %#lx\n",
246
                start_mem, end_mem);
247
#endif
248
 
249
        /*
250
         * initialize the bad page table and bad page to point
251
         * to a couple of allocated pages
252
         */
253
        empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
254
        empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
255
        empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
256
        memset((void *)empty_zero_page, 0, PAGE_SIZE);
257
 
258
        /*
259
         * Set up SFC/DFC registers (user data space)
260
         */
261
        set_fs (USER_DS);
262
 
263
#ifdef DEBUG
264
        printk ("before free_area_init\n");
265
#endif
266
        zones_size[0] = (mach_max_dma_address < (unsigned long)high_memory ?
267
                         mach_max_dma_address : (unsigned long)high_memory);
268
        zones_size[1] = (unsigned long)high_memory - zones_size[0];
269
 
270
        zones_size[0] = (zones_size[0] - PAGE_OFFSET) >> PAGE_SHIFT;
271
        zones_size[1] >>= PAGE_SHIFT;
272
 
273
        free_area_init(zones_size);
274
}
275
 
276
extern char __init_begin, __init_end;
277
extern unsigned long totalram_pages;
278
 
279
void free_initmem(void)
280
{
281
        unsigned long addr;
282
 
283
        addr = (unsigned long)&__init_begin;
284
        for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) {
285
                virt_to_page(addr)->flags &= ~(1 << PG_reserved);
286
                set_page_count(virt_to_page(addr), 1);
287
                free_page(addr);
288
                totalram_pages++;
289
        }
290
}
291
 
292
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.