1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * linux/arch/m68k/mm/sun3mmu.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Implementations of mm routines specific to the sun3 MMU.
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Moved here 8/20/1999 Sam Creasey
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <linux/signal.h>
12*4882a593Smuzhiyun #include <linux/sched.h>
13*4882a593Smuzhiyun #include <linux/mm.h>
14*4882a593Smuzhiyun #include <linux/swap.h>
15*4882a593Smuzhiyun #include <linux/kernel.h>
16*4882a593Smuzhiyun #include <linux/string.h>
17*4882a593Smuzhiyun #include <linux/types.h>
18*4882a593Smuzhiyun #include <linux/init.h>
19*4882a593Smuzhiyun #include <linux/memblock.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #include <asm/setup.h>
22*4882a593Smuzhiyun #include <linux/uaccess.h>
23*4882a593Smuzhiyun #include <asm/page.h>
24*4882a593Smuzhiyun #include <asm/machdep.h>
25*4882a593Smuzhiyun #include <asm/io.h>
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun extern void mmu_emu_init (unsigned long bootmem_end);
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun extern unsigned long num_pages;
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /* For the sun3 we try to follow the i386 paging_init() more closely */
34*4882a593Smuzhiyun /* start_mem and end_mem have PAGE_OFFSET added already */
35*4882a593Smuzhiyun /* now sets up tables using sun3 PTEs rather than i386 as before. --m */
paging_init(void)36*4882a593Smuzhiyun void __init paging_init(void)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun pgd_t * pg_dir;
39*4882a593Smuzhiyun pte_t * pg_table;
40*4882a593Smuzhiyun int i;
41*4882a593Smuzhiyun unsigned long address;
42*4882a593Smuzhiyun unsigned long next_pgtable;
43*4882a593Smuzhiyun unsigned long bootmem_end;
44*4882a593Smuzhiyun unsigned long max_zone_pfn[MAX_NR_ZONES] = { 0, };
45*4882a593Smuzhiyun unsigned long size;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun empty_zero_page = memblock_alloc(PAGE_SIZE, PAGE_SIZE);
48*4882a593Smuzhiyun if (!empty_zero_page)
49*4882a593Smuzhiyun panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
50*4882a593Smuzhiyun __func__, PAGE_SIZE, PAGE_SIZE);
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun address = PAGE_OFFSET;
53*4882a593Smuzhiyun pg_dir = swapper_pg_dir;
54*4882a593Smuzhiyun memset (swapper_pg_dir, 0, sizeof (swapper_pg_dir));
55*4882a593Smuzhiyun memset (kernel_pg_dir, 0, sizeof (kernel_pg_dir));
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun size = num_pages * sizeof(pte_t);
58*4882a593Smuzhiyun size = (size + PAGE_SIZE) & ~(PAGE_SIZE-1);
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun next_pgtable = (unsigned long)memblock_alloc(size, PAGE_SIZE);
61*4882a593Smuzhiyun if (!next_pgtable)
62*4882a593Smuzhiyun panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
63*4882a593Smuzhiyun __func__, size, PAGE_SIZE);
64*4882a593Smuzhiyun bootmem_end = (next_pgtable + size + PAGE_SIZE) & PAGE_MASK;
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun /* Map whole memory from PAGE_OFFSET (0x0E000000) */
67*4882a593Smuzhiyun pg_dir += PAGE_OFFSET >> PGDIR_SHIFT;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun while (address < (unsigned long)high_memory) {
70*4882a593Smuzhiyun pg_table = (pte_t *) __pa (next_pgtable);
71*4882a593Smuzhiyun next_pgtable += PTRS_PER_PTE * sizeof (pte_t);
72*4882a593Smuzhiyun pgd_val(*pg_dir) = (unsigned long) pg_table;
73*4882a593Smuzhiyun pg_dir++;
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun /* now change pg_table to kernel virtual addresses */
76*4882a593Smuzhiyun pg_table = (pte_t *) __va ((unsigned long) pg_table);
77*4882a593Smuzhiyun for (i=0; i<PTRS_PER_PTE; ++i, ++pg_table) {
78*4882a593Smuzhiyun pte_t pte = pfn_pte(virt_to_pfn(address), PAGE_INIT);
79*4882a593Smuzhiyun if (address >= (unsigned long)high_memory)
80*4882a593Smuzhiyun pte_val (pte) = 0;
81*4882a593Smuzhiyun set_pte (pg_table, pte);
82*4882a593Smuzhiyun address += PAGE_SIZE;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun mmu_emu_init(bootmem_end);
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun current->mm = NULL;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* memory sizing is a hack stolen from motorola.c.. hope it works for us */
91*4882a593Smuzhiyun max_zone_pfn[ZONE_DMA] = ((unsigned long)high_memory) >> PAGE_SHIFT;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun /* I really wish I knew why the following change made things better... -- Sam */
94*4882a593Smuzhiyun free_area_init(max_zone_pfn);
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun }
98