File Index
Files and directories
Sign in
FILE

8xx.c

File preview with syntax highlighting.

linux-6.19.14/arch/powerpc/mm/nohash/8xx.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * This file contains the routines for initializing the MMU
  4 * on the 8xx series of chips.
  5 *  -- christophe
  6 *
  7 *  Derived from arch/powerpc/mm/40x_mmu.c:
  8 */
  9
 10#include <linux/memblock.h>
 11#include <linux/hugetlb.h>
 12
 13#include <asm/fixmap.h>
 14#include <asm/pgalloc.h>
 15
 16#include <mm/mmu_decl.h>
 17
 18#define IMMR_SIZE (FIX_IMMR_SIZE << PAGE_SHIFT)
 19
 20static unsigned long block_mapped_ram;
 21
 22/*
 23 * Return PA for this VA if it is in an area mapped with LTLBs or fixmap.
 24 * Otherwise, returns 0
 25 */
 26phys_addr_t v_block_mapped(unsigned long va)
 27{
 28	unsigned long p = PHYS_IMMR_BASE;
 29
 30	if (va >= VIRT_IMMR_BASE && va < VIRT_IMMR_BASE + IMMR_SIZE)
 31		return p + va - VIRT_IMMR_BASE;
 32	if (va >= PAGE_OFFSET && va < PAGE_OFFSET + block_mapped_ram)
 33		return __pa(va);
 34	return 0;
 35}
 36
 37/*
 38 * Return VA for a given PA mapped with LTLBs or fixmap
 39 * Return 0 if not mapped
 40 */
 41unsigned long p_block_mapped(phys_addr_t pa)
 42{
 43	unsigned long p = PHYS_IMMR_BASE;
 44
 45	if (pa >= p && pa < p + IMMR_SIZE)
 46		return VIRT_IMMR_BASE + pa - p;
 47	if (pa < block_mapped_ram)
 48		return (unsigned long)__va(pa);
 49	return 0;
 50}
 51
 52static int __ref __early_map_kernel_hugepage(unsigned long va, phys_addr_t pa,
 53					     pgprot_t prot, int psize, bool new)
 54{
 55	pmd_t *pmdp = pmd_off_k(va);
 56	pte_t *ptep;
 57	unsigned int shift = mmu_psize_to_shift(psize);
 58
 59	if (new) {
 60		if (WARN_ON(slab_is_available()))
 61			return -EINVAL;
 62
 63		if (psize == MMU_PAGE_8M) {
 64			if (WARN_ON(!pmd_none(*pmdp) || !pmd_none(*(pmdp + 1))))
 65				return -EINVAL;
 66
 67			ptep = early_alloc_pgtable(PTE_FRAG_SIZE);
 68			pmd_populate_kernel(&init_mm, pmdp, ptep);
 69
 70			ptep = early_alloc_pgtable(PTE_FRAG_SIZE);
 71			pmd_populate_kernel(&init_mm, pmdp + 1, ptep);
 72
 73			ptep = (pte_t *)pmdp;
 74		} else {
 75			ptep = early_pte_alloc_kernel(pmdp, va);
 76			/* The PTE should never be already present */
 77			if (WARN_ON(pte_present(*ptep) && pgprot_val(prot)))
 78				return -EINVAL;
 79		}
 80	} else {
 81		if (psize == MMU_PAGE_8M)
 82			ptep = (pte_t *)pmdp;
 83		else
 84			ptep = pte_offset_kernel(pmdp, va);
 85	}
 86
 87	if (WARN_ON(!ptep))
 88		return -ENOMEM;
 89
 90	set_huge_pte_at(&init_mm, va, ptep,
 91			arch_make_huge_pte(pfn_pte(pa >> PAGE_SHIFT, prot), shift, 0),
 92			1UL << shift);
 93
 94	return 0;
 95}
 96
 97/*
 98 * MMU_init_hw does the chip-specific initialization of the MMU hardware.
 99 */
100void __init MMU_init_hw(void)
101{
102}
103
104static bool immr_is_mapped __initdata;
105
106void __init mmu_mapin_immr(void)
107{
108	if (immr_is_mapped)
109		return;
110
111	immr_is_mapped = true;
112
113	__early_map_kernel_hugepage(VIRT_IMMR_BASE, PHYS_IMMR_BASE,
114				    PAGE_KERNEL_NCG, MMU_PAGE_512K, true);
115}
116
117static int mmu_mapin_ram_chunk(unsigned long offset, unsigned long top,
118			       pgprot_t prot, bool new)
119{
120	unsigned long v = PAGE_OFFSET + offset;
121	unsigned long p = offset;
122	int err = 0;
123
124	WARN_ON(!IS_ALIGNED(offset, SZ_16K) || !IS_ALIGNED(top, SZ_16K));
125
126	for (; p < ALIGN(p, SZ_512K) && p < top && !err; p += SZ_16K, v += SZ_16K)
127		err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_16K, new);
128	for (; p < ALIGN(p, SZ_8M) && p < top && !err; p += SZ_512K, v += SZ_512K)
129		err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_512K, new);
130	for (; p < ALIGN_DOWN(top, SZ_8M) && p < top && !err; p += SZ_8M, v += SZ_8M)
131		err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_8M, new);
132	for (; p < ALIGN_DOWN(top, SZ_512K) && p < top && !err; p += SZ_512K, v += SZ_512K)
133		err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_512K, new);
134	for (; p < ALIGN_DOWN(top, SZ_16K) && p < top && !err; p += SZ_16K, v += SZ_16K)
135		err = __early_map_kernel_hugepage(v, p, prot, MMU_PAGE_16K, new);
136
137	if (!new)
138		flush_tlb_kernel_range(PAGE_OFFSET + v, PAGE_OFFSET + top);
139
140	return err;
141}
142
143unsigned long __init mmu_mapin_ram(unsigned long base, unsigned long top)
144{
145	unsigned long etext8 = ALIGN(__pa(_etext), SZ_8M);
146	unsigned long sinittext = __pa(_sinittext);
147	bool strict_boundary = strict_kernel_rwx_enabled() || debug_pagealloc_enabled_or_kfence();
148	unsigned long boundary = strict_boundary ? sinittext : etext8;
149	unsigned long einittext8 = ALIGN(__pa(_einittext), SZ_8M);
150
151	WARN_ON(top < einittext8);
152
153	mmu_mapin_immr();
154
155	mmu_mapin_ram_chunk(0, boundary, PAGE_KERNEL_X, true);
156	if (debug_pagealloc_enabled_or_kfence()) {
157		top = boundary;
158	} else {
159		mmu_mapin_ram_chunk(boundary, einittext8, PAGE_KERNEL_X, true);
160		mmu_mapin_ram_chunk(einittext8, top, PAGE_KERNEL, true);
161	}
162
163	if (top > SZ_32M)
164		memblock_set_current_limit(top);
165
166	block_mapped_ram = top;
167
168	return top;
169}
170
171int mmu_mark_initmem_nx(void)
172{
173	unsigned long etext8 = ALIGN(__pa(_etext), SZ_8M);
174	unsigned long sinittext = __pa(_sinittext);
175	unsigned long boundary = strict_kernel_rwx_enabled() ? sinittext : etext8;
176	unsigned long einittext8 = ALIGN(__pa(_einittext), SZ_8M);
177	int err = 0;
178
179	if (!debug_pagealloc_enabled_or_kfence())
180		err = mmu_mapin_ram_chunk(boundary, einittext8, PAGE_KERNEL, false);
181
182	if (IS_ENABLED(CONFIG_PIN_TLB_TEXT))
183		mmu_pin_tlb(block_mapped_ram, false);
184
185	return err;
186}
187
188#ifdef CONFIG_STRICT_KERNEL_RWX
189int mmu_mark_rodata_ro(void)
190{
191	unsigned long sinittext = __pa(_sinittext);
192	int err;
193
194	err = mmu_mapin_ram_chunk(0, sinittext, PAGE_KERNEL_ROX, false);
195	if (IS_ENABLED(CONFIG_PIN_TLB_DATA))
196		mmu_pin_tlb(block_mapped_ram, true);
197
198	return err;
199}
200#endif
201
202void __init setup_initial_memory_limit(phys_addr_t first_memblock_base,
203				       phys_addr_t first_memblock_size)
204{
205	/* We don't currently support the first MEMBLOCK not mapping 0
206	 * physical on those processors
207	 */
208	BUG_ON(first_memblock_base != 0);
209
210	/* 8xx can only access 32MB at the moment */
211	memblock_set_current_limit(min_t(u64, first_memblock_size, SZ_32M));
212
213	BUILD_BUG_ON(ALIGN_DOWN(MODULES_VADDR, PGDIR_SIZE) < TASK_SIZE);
214}
215
216int pud_clear_huge(pud_t *pud)
217{
218	 return 0;
219}
220
221int pmd_clear_huge(pmd_t *pmd)
222{
223	 return 0;
224}
~/ Read-only file preview.