Skip to content

Commit 93c0651

Browse files
riscv: support for Svpbmt and D1 memory types
Adds support for Svpbmt, the "Supervisor-mode: page-based memory types" extension, which allows pages to be marked as non-cacheable and/or I/O. This also includes support for the Allwinner D1's page table attributes via the alternatives framework, which differ from Svpbmt in various ways but are necessary to make the D1 function. * palmer/riscv-d1: riscv: add memory-type errata for T-Head riscv: don't use global static vars to store alternative data riscv: remove FIXMAP_PAGE_IO and fall back to its default value riscv: add RISC-V Svpbmt extension support riscv: Fix accessing pfn bits in PTEs for non-32bit variants riscv: move boot alternatives to after fill_hwcap riscv: prevent compressed instructions in alternatives riscv: extend concatenated alternatives-lines to the same length riscv: implement ALTERNATIVE_2 macro riscv: implement module alternatives riscv: allow different stages with alternatives riscv: integrate alternatives better into the main architecture
2 parents d26eee7 + a35707c commit 93c0651

28 files changed

Lines changed: 724 additions & 161 deletions

arch/riscv/Kconfig

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,21 @@ config NODES_SHIFT
324324
Specify the maximum number of NUMA Nodes available on the target
325325
system. Increases memory reserved to accommodate various tables.
326326

327+
config RISCV_ALTERNATIVE
328+
bool
329+
depends on !XIP_KERNEL
330+
help
331+
This Kconfig allows the kernel to automatically patch the
332+
errata required by the execution platform at run time. The
333+
code patching is performed once in the boot stages. It means
334+
that the overhead from this mechanism is just taken once.
335+
336+
config RISCV_ALTERNATIVE_EARLY
337+
bool
338+
depends on RISCV_ALTERNATIVE
339+
help
340+
Allows early patching of the kernel for special errata
341+
327342
config RISCV_ISA_C
328343
bool "Emit compressed instructions when building Linux"
329344
default y
@@ -334,6 +349,19 @@ config RISCV_ISA_C
334349

335350
If you don't know what to do here, say Y.
336351

352+
config RISCV_ISA_SVPBMT
353+
bool "SVPBMT extension support"
354+
depends on 64BIT && MMU
355+
select RISCV_ALTERNATIVE
356+
default y
357+
help
358+
Adds support to dynamically detect the presence of the SVPBMT extension
359+
(Supervisor-mode: page-based memory types) and enable its usage.
360+
361+
The SVPBMT extension is only available on 64Bit cpus.
362+
363+
If you don't know what to do here, say Y.
364+
337365
config FPU
338366
bool "FPU support"
339367
default y

arch/riscv/Kconfig.erratas

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
11
menu "CPU errata selection"
22

3-
config RISCV_ERRATA_ALTERNATIVE
4-
bool "RISC-V alternative scheme"
5-
depends on !XIP_KERNEL
6-
default y
7-
help
8-
This Kconfig allows the kernel to automatically patch the
9-
errata required by the execution platform at run time. The
10-
code patching is performed once in the boot stages. It means
11-
that the overhead from this mechanism is just taken once.
12-
133
config ERRATA_SIFIVE
144
bool "SiFive errata"
15-
depends on RISCV_ERRATA_ALTERNATIVE
5+
depends on !XIP_KERNEL
6+
select RISCV_ALTERNATIVE
167
help
178
All SiFive errata Kconfig depend on this Kconfig. Disabling
189
this Kconfig will disable all SiFive errata. Please say "Y"
@@ -42,4 +33,25 @@ config ERRATA_SIFIVE_CIP_1200
4233

4334
If you don't know what to do here, say "Y".
4435

36+
config ERRATA_THEAD
37+
bool "T-HEAD errata"
38+
select RISCV_ALTERNATIVE
39+
help
40+
All T-HEAD errata Kconfig depend on this Kconfig. Disabling
41+
this Kconfig will disable all T-HEAD errata. Please say "Y"
42+
here if your platform uses T-HEAD CPU cores.
43+
44+
Otherwise, please say "N" here to avoid unnecessary overhead.
45+
46+
config ERRATA_THEAD_PBMT
47+
bool "Apply T-Head memory type errata"
48+
depends on ERRATA_THEAD && 64BIT
49+
select RISCV_ALTERNATIVE_EARLY
50+
default y
51+
help
52+
This will apply the memory type errata to handle the non-standard
53+
memory type bits in page-table-entries on T-Head SoCs.
54+
55+
If you don't know what to do here, say "Y".
56+
4557
endmenu

arch/riscv/Kconfig.socs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ config SOC_SIFIVE
1414
select CLK_SIFIVE
1515
select CLK_SIFIVE_PRCI
1616
select SIFIVE_PLIC
17-
select RISCV_ERRATA_ALTERNATIVE if !XIP_KERNEL
1817
select ERRATA_SIFIVE if !XIP_KERNEL
1918
help
2019
This enables support for SiFive SoC platform hardware.

arch/riscv/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ endif
103103

104104
head-y := arch/riscv/kernel/head.o
105105

106-
core-$(CONFIG_RISCV_ERRATA_ALTERNATIVE) += arch/riscv/errata/
106+
core-y += arch/riscv/errata/
107107
core-$(CONFIG_KVM) += arch/riscv/kvm/
108108

109109
libs-y += arch/riscv/lib/

arch/riscv/errata/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
obj-y += alternative.o
21
obj-$(CONFIG_ERRATA_SIFIVE) += sifive/
2+
obj-$(CONFIG_ERRATA_THEAD) += thead/

arch/riscv/errata/alternative.c

Lines changed: 0 additions & 75 deletions
This file was deleted.

arch/riscv/errata/sifive/errata.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
#include <linux/kernel.h>
7+
#include <linux/module.h>
78
#include <linux/string.h>
89
#include <linux/bug.h>
910
#include <asm/patch.h>
@@ -54,7 +55,8 @@ static struct errata_info_t errata_list[ERRATA_SIFIVE_NUMBER] = {
5455
},
5556
};
5657

57-
static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid)
58+
static u32 __init_or_module sifive_errata_probe(unsigned long archid,
59+
unsigned long impid)
5860
{
5961
int idx;
6062
u32 cpu_req_errata = 0;
@@ -66,7 +68,7 @@ static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid)
6668
return cpu_req_errata;
6769
}
6870

69-
static void __init warn_miss_errata(u32 miss_errata)
71+
static void __init_or_module warn_miss_errata(u32 miss_errata)
7072
{
7173
int i;
7274

@@ -79,14 +81,22 @@ static void __init warn_miss_errata(u32 miss_errata)
7981
pr_warn("----------------------------------------------------------------\n");
8082
}
8183

82-
void __init sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
83-
unsigned long archid, unsigned long impid)
84+
void __init_or_module sifive_errata_patch_func(struct alt_entry *begin,
85+
struct alt_entry *end,
86+
unsigned long archid,
87+
unsigned long impid,
88+
unsigned int stage)
8489
{
8590
struct alt_entry *alt;
86-
u32 cpu_req_errata = sifive_errata_probe(archid, impid);
91+
u32 cpu_req_errata;
8792
u32 cpu_apply_errata = 0;
8893
u32 tmp;
8994

95+
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
96+
return;
97+
98+
cpu_req_errata = sifive_errata_probe(archid, impid);
99+
90100
for (alt = begin; alt < end; alt++) {
91101
if (alt->vendor_id != SIFIVE_VENDOR_ID)
92102
continue;

arch/riscv/errata/thead/Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
ifdef CONFIG_RISCV_ALTERNATIVE_EARLY
2+
CFLAGS_errata.o := -mcmodel=medany
3+
ifdef CONFIG_FTRACE
4+
CFLAGS_REMOVE_errata.o = $(CC_FLAGS_FTRACE)
5+
endif
6+
ifdef CONFIG_KASAN
7+
KASAN_SANITIZE_errata.o := n
8+
endif
9+
endif
10+
11+
obj-y += errata.o

arch/riscv/errata/thead/errata.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (C) 2021 Heiko Stuebner <heiko@sntech.de>
4+
*/
5+
6+
#include <linux/bug.h>
7+
#include <linux/kernel.h>
8+
#include <linux/module.h>
9+
#include <linux/string.h>
10+
#include <linux/uaccess.h>
11+
#include <asm/alternative.h>
12+
#include <asm/cacheflush.h>
13+
#include <asm/errata_list.h>
14+
#include <asm/patch.h>
15+
#include <asm/vendorid_list.h>
16+
17+
struct errata_info {
18+
char name[ERRATA_STRING_LENGTH_MAX];
19+
bool (*check_func)(unsigned long arch_id, unsigned long impid);
20+
unsigned int stage;
21+
};
22+
23+
static bool errata_mt_check_func(unsigned long arch_id, unsigned long impid)
24+
{
25+
if (arch_id != 0 || impid != 0)
26+
return false;
27+
return true;
28+
}
29+
30+
static const struct errata_info errata_list[ERRATA_THEAD_NUMBER] = {
31+
{
32+
.name = "memory-types",
33+
.stage = RISCV_ALTERNATIVES_EARLY_BOOT,
34+
.check_func = errata_mt_check_func
35+
},
36+
};
37+
38+
static u32 thead_errata_probe(unsigned int stage, unsigned long archid, unsigned long impid)
39+
{
40+
const struct errata_info *info;
41+
u32 cpu_req_errata = 0;
42+
int idx;
43+
44+
for (idx = 0; idx < ERRATA_THEAD_NUMBER; idx++) {
45+
info = &errata_list[idx];
46+
47+
if ((stage == RISCV_ALTERNATIVES_MODULE ||
48+
info->stage == stage) && info->check_func(archid, impid))
49+
cpu_req_errata |= (1U << idx);
50+
}
51+
52+
return cpu_req_errata;
53+
}
54+
55+
void __init_or_module thead_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
56+
unsigned long archid, unsigned long impid,
57+
unsigned int stage)
58+
{
59+
struct alt_entry *alt;
60+
u32 cpu_req_errata = thead_errata_probe(stage, archid, impid);
61+
u32 tmp;
62+
63+
for (alt = begin; alt < end; alt++) {
64+
if (alt->vendor_id != THEAD_VENDOR_ID)
65+
continue;
66+
if (alt->errata_id >= ERRATA_THEAD_NUMBER)
67+
continue;
68+
69+
tmp = (1U << alt->errata_id);
70+
if (cpu_req_errata & tmp) {
71+
/* On vm-alternatives, the mmu isn't running yet */
72+
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
73+
memcpy((void *)__pa_symbol(alt->old_ptr),
74+
(void *)__pa_symbol(alt->alt_ptr), alt->alt_len);
75+
else
76+
patch_text_nosync(alt->old_ptr, alt->alt_ptr, alt->alt_len);
77+
}
78+
}
79+
80+
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
81+
local_flush_icache_all();
82+
}

0 commit comments

Comments
 (0)