Skip to content

Commit f2c17aa

Browse files
committed
RISC-V: Implement compile-time fixed mappings
This patch implements compile-time virtual to physical mappings. These compile-time fixed mappings can be used by earlycon, ACPI, and early ioremap for creating fixed mappings when FIX_EARLYCON_MEM=y. To start with, we have enabled compile-time fixed mappings for earlycon. Signed-off-by: Anup Patel <anup.patel@wdc.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Palmer Dabbelt <palmer@sifive.com>
1 parent 6f1e9e9 commit f2c17aa

File tree

3 files changed

+81
-0
lines changed

3 files changed

+81
-0
lines changed

arch/riscv/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ config GENERIC_CSUM
8989
config GENERIC_HWEIGHT
9090
def_bool y
9191

92+
config FIX_EARLYCON_MEM
93+
def_bool y
94+
9295
config PGTABLE_LEVELS
9396
int
9497
default 3 if 64BIT

arch/riscv/include/asm/fixmap.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Copyright (C) 2019 Western Digital Corporation or its affiliates.
4+
*/
5+
6+
#ifndef _ASM_RISCV_FIXMAP_H
7+
#define _ASM_RISCV_FIXMAP_H
8+
9+
#include <linux/kernel.h>
10+
#include <linux/sizes.h>
11+
#include <asm/page.h>
12+
#include <asm/pgtable.h>
13+
14+
/*
15+
* Here we define all the compile-time 'special' virtual addresses.
16+
* The point is to have a constant address at compile time, but to
17+
* set the physical address only in the boot process.
18+
*
19+
* These 'compile-time allocated' memory buffers are page-sized. Use
20+
* set_fixmap(idx,phys) to associate physical memory with fixmap indices.
21+
*/
22+
enum fixed_addresses {
23+
FIX_HOLE,
24+
FIX_EARLYCON_MEM_BASE,
25+
__end_of_fixed_addresses
26+
};
27+
28+
#define FIXADDR_SIZE (__end_of_fixed_addresses * PAGE_SIZE)
29+
#define FIXADDR_TOP (PAGE_OFFSET)
30+
#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
31+
32+
#define FIXMAP_PAGE_IO PAGE_KERNEL
33+
34+
#define __early_set_fixmap __set_fixmap
35+
36+
#define __late_set_fixmap __set_fixmap
37+
#define __late_clear_fixmap(idx) __set_fixmap((idx), 0, FIXMAP_PAGE_CLEAR)
38+
39+
extern void __set_fixmap(enum fixed_addresses idx,
40+
phys_addr_t phys, pgprot_t prot);
41+
42+
#include <asm-generic/fixmap.h>
43+
44+
#endif /* _ASM_RISCV_FIXMAP_H */

arch/riscv/mm/init.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/sizes.h>
2020
#include <linux/of_fdt.h>
2121

22+
#include <asm/fixmap.h>
2223
#include <asm/tlbflush.h>
2324
#include <asm/sections.h>
2425
#include <asm/pgtable.h>
@@ -148,8 +149,28 @@ pgd_t trampoline_pg_dir[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
148149
#define NUM_SWAPPER_PMDS ((uintptr_t)-PAGE_OFFSET >> PGDIR_SHIFT)
149150
pmd_t swapper_pmd[PTRS_PER_PMD*((-PAGE_OFFSET)/PGDIR_SIZE)] __page_aligned_bss;
150151
pmd_t trampoline_pmd[PTRS_PER_PGD] __initdata __aligned(PAGE_SIZE);
152+
pmd_t fixmap_pmd[PTRS_PER_PMD] __page_aligned_bss;
151153
#endif
152154

155+
pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss;
156+
157+
void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
158+
{
159+
unsigned long addr = __fix_to_virt(idx);
160+
pte_t *ptep;
161+
162+
BUG_ON(idx <= FIX_HOLE || idx >= __end_of_fixed_addresses);
163+
164+
ptep = &fixmap_pte[pte_index(addr)];
165+
166+
if (pgprot_val(prot)) {
167+
set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
168+
} else {
169+
pte_clear(&init_mm, addr, ptep);
170+
local_flush_tlb_page(addr);
171+
}
172+
}
173+
153174
asmlinkage void __init setup_vm(void)
154175
{
155176
extern char _start;
@@ -172,20 +193,33 @@ asmlinkage void __init setup_vm(void)
172193

173194
for (i = 0; i < (-PAGE_OFFSET)/PGDIR_SIZE; ++i) {
174195
size_t o = (PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD + i;
196+
175197
swapper_pg_dir[o] =
176198
pfn_pgd(PFN_DOWN((uintptr_t)swapper_pmd) + i,
177199
__pgprot(_PAGE_TABLE));
178200
}
179201
for (i = 0; i < ARRAY_SIZE(swapper_pmd); i++)
180202
swapper_pmd[i] = pfn_pmd(PFN_DOWN(pa + i * PMD_SIZE), prot);
203+
204+
swapper_pg_dir[(FIXADDR_START >> PGDIR_SHIFT) % PTRS_PER_PGD] =
205+
pfn_pgd(PFN_DOWN((uintptr_t)fixmap_pmd),
206+
__pgprot(_PAGE_TABLE));
207+
fixmap_pmd[(FIXADDR_START >> PMD_SHIFT) % PTRS_PER_PMD] =
208+
pfn_pmd(PFN_DOWN((uintptr_t)fixmap_pte),
209+
__pgprot(_PAGE_TABLE));
181210
#else
182211
trampoline_pg_dir[(PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD] =
183212
pfn_pgd(PFN_DOWN(pa), prot);
184213

185214
for (i = 0; i < (-PAGE_OFFSET)/PGDIR_SIZE; ++i) {
186215
size_t o = (PAGE_OFFSET >> PGDIR_SHIFT) % PTRS_PER_PGD + i;
216+
187217
swapper_pg_dir[o] =
188218
pfn_pgd(PFN_DOWN(pa + i * PGDIR_SIZE), prot);
189219
}
220+
221+
swapper_pg_dir[(FIXADDR_START >> PGDIR_SHIFT) % PTRS_PER_PGD] =
222+
pfn_pgd(PFN_DOWN((uintptr_t)fixmap_pte),
223+
__pgprot(_PAGE_TABLE));
190224
#endif
191225
}

0 commit comments

Comments
 (0)