Skip to content

Commit 4bf9706

Browse files
charlie-rivospalmer-dabbelt
authored andcommitted
riscv: Add ghostwrite vulnerability
Follow the patterns of the other architectures that use GENERIC_CPU_VULNERABILITIES for riscv to introduce the ghostwrite vulnerability and mitigation. The mitigation is to disable all vector which is accomplished by clearing the bit from the cpufeature field. Ghostwrite only affects thead c9xx CPUs that impelment xtheadvector, so the vulerability will only be mitigated on these CPUs. Signed-off-by: Charlie Jenkins <[email protected]> Tested-by: Yangyu Chen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent c384c5d commit 4bf9706

File tree

9 files changed

+138
-2
lines changed

9 files changed

+138
-2
lines changed

arch/riscv/Kconfig.errata

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,15 @@ config ERRATA_THEAD_PMU
119119

120120
If you don't know what to do here, say "Y".
121121

122+
config ERRATA_THEAD_GHOSTWRITE
123+
bool "Apply T-Head Ghostwrite errata"
124+
depends on ERRATA_THEAD && RISCV_ISA_XTHEADVECTOR
125+
default y
126+
help
127+
The T-Head C9xx cores have a vulnerability in the xtheadvector
128+
instruction set. When this errata is enabled, the CPUs will be probed
129+
to determine if they are vulnerable and disable xtheadvector.
130+
131+
If you don't know what to do here, say "Y".
132+
122133
endmenu # "CPU errata selection"

arch/riscv/errata/thead/errata.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <linux/string.h>
1111
#include <linux/uaccess.h>
1212
#include <asm/alternative.h>
13+
#include <asm/bugs.h>
1314
#include <asm/cacheflush.h>
1415
#include <asm/cpufeature.h>
1516
#include <asm/dma-noncoherent.h>
@@ -142,6 +143,31 @@ static bool errata_probe_pmu(unsigned int stage,
142143
return true;
143144
}
144145

146+
static bool errata_probe_ghostwrite(unsigned int stage,
147+
unsigned long arch_id, unsigned long impid)
148+
{
149+
if (!IS_ENABLED(CONFIG_ERRATA_THEAD_GHOSTWRITE))
150+
return false;
151+
152+
/*
153+
* target-c9xx cores report arch_id and impid as 0
154+
*
155+
* While ghostwrite may not affect all c9xx cores that implement
156+
* xtheadvector, there is no futher granularity than c9xx. Assume
157+
* vulnerable for this entire class of processors when xtheadvector is
158+
* enabled.
159+
*/
160+
if (arch_id != 0 || impid != 0)
161+
return false;
162+
163+
if (stage != RISCV_ALTERNATIVES_EARLY_BOOT)
164+
return false;
165+
166+
ghostwrite_set_vulnerable();
167+
168+
return true;
169+
}
170+
145171
static u32 thead_errata_probe(unsigned int stage,
146172
unsigned long archid, unsigned long impid)
147173
{
@@ -155,6 +181,8 @@ static u32 thead_errata_probe(unsigned int stage,
155181
if (errata_probe_pmu(stage, archid, impid))
156182
cpu_req_errata |= BIT(ERRATA_THEAD_PMU);
157183

184+
errata_probe_ghostwrite(stage, archid, impid);
185+
158186
return cpu_req_errata;
159187
}
160188

arch/riscv/include/asm/bugs.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Interface for managing mitigations for riscv vulnerabilities.
4+
*
5+
* Copyright (C) 2024 Rivos Inc.
6+
*/
7+
8+
#ifndef __ASM_BUGS_H
9+
#define __ASM_BUGS_H
10+
11+
/* Watch out, ordering is important here. */
12+
enum mitigation_state {
13+
UNAFFECTED,
14+
MITIGATED,
15+
VULNERABLE,
16+
};
17+
18+
void ghostwrite_set_vulnerable(void);
19+
bool ghostwrite_enable_mitigation(void);
20+
enum mitigation_state ghostwrite_get_state(void);
21+
22+
#endif /* __ASM_BUGS_H */

arch/riscv/include/asm/errata_list.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
#ifdef CONFIG_ERRATA_THEAD
2626
#define ERRATA_THEAD_MAE 0
2727
#define ERRATA_THEAD_PMU 1
28-
#define ERRATA_THEAD_NUMBER 2
28+
#define ERRATA_THEAD_GHOSTWRITE 2
29+
#define ERRATA_THEAD_NUMBER 3
2930
#endif
3031

3132
#ifdef __ASSEMBLY__

arch/riscv/kernel/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,5 @@ obj-$(CONFIG_COMPAT) += compat_vdso/
118118
obj-$(CONFIG_64BIT) += pi/
119119
obj-$(CONFIG_ACPI) += acpi.o
120120
obj-$(CONFIG_ACPI_NUMA) += acpi_numa.o
121+
122+
obj-$(CONFIG_GENERIC_CPU_VULNERABILITIES) += bugs.o

arch/riscv/kernel/bugs.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* Copyright (C) 2024 Rivos Inc.
4+
*/
5+
6+
#include <linux/cpu.h>
7+
#include <linux/device.h>
8+
#include <linux/sprintf.h>
9+
10+
#include <asm/bugs.h>
11+
#include <asm/vendor_extensions/thead.h>
12+
13+
static enum mitigation_state ghostwrite_state;
14+
15+
void ghostwrite_set_vulnerable(void)
16+
{
17+
ghostwrite_state = VULNERABLE;
18+
}
19+
20+
/*
21+
* Vendor extension alternatives will use the value set at the time of boot
22+
* alternative patching, thus this must be called before boot alternatives are
23+
* patched (and after extension probing) to be effective.
24+
*
25+
* Returns true if mitgated, false otherwise.
26+
*/
27+
bool ghostwrite_enable_mitigation(void)
28+
{
29+
if (IS_ENABLED(CONFIG_RISCV_ISA_XTHEADVECTOR) &&
30+
ghostwrite_state == VULNERABLE && !cpu_mitigations_off()) {
31+
disable_xtheadvector();
32+
ghostwrite_state = MITIGATED;
33+
return true;
34+
}
35+
36+
return false;
37+
}
38+
39+
enum mitigation_state ghostwrite_get_state(void)
40+
{
41+
return ghostwrite_state;
42+
}
43+
44+
ssize_t cpu_show_ghostwrite(struct device *dev, struct device_attribute *attr, char *buf)
45+
{
46+
if (IS_ENABLED(CONFIG_RISCV_ISA_XTHEADVECTOR)) {
47+
switch (ghostwrite_state) {
48+
case UNAFFECTED:
49+
return sprintf(buf, "Not affected\n");
50+
case MITIGATED:
51+
return sprintf(buf, "Mitigation: xtheadvector disabled\n");
52+
case VULNERABLE:
53+
fallthrough;
54+
default:
55+
return sprintf(buf, "Vulnerable\n");
56+
}
57+
} else {
58+
return sprintf(buf, "Not affected\n");
59+
}
60+
}

arch/riscv/kernel/cpufeature.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <linux/of.h>
1818
#include <asm/acpi.h>
1919
#include <asm/alternative.h>
20+
#include <asm/bugs.h>
2021
#include <asm/cacheflush.h>
2122
#include <asm/cpufeature.h>
2223
#include <asm/hwcap.h>
@@ -824,6 +825,7 @@ static int has_thead_homogeneous_vlenb(void)
824825
static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
825826
{
826827
unsigned int cpu;
828+
bool mitigated;
827829

828830
for_each_possible_cpu(cpu) {
829831
unsigned long this_hwcap = 0;
@@ -874,7 +876,13 @@ static int __init riscv_fill_hwcap_from_ext_list(unsigned long *isa2hwcap)
874876
riscv_fill_vendor_ext_list(cpu);
875877
}
876878

877-
if (has_xtheadvector_no_alternatives() && has_thead_homogeneous_vlenb() < 0) {
879+
/*
880+
* Execute ghostwrite mitigation immediately after detecting extensions
881+
* to disable xtheadvector if necessary.
882+
*/
883+
mitigated = ghostwrite_enable_mitigation();
884+
885+
if (!mitigated && has_xtheadvector_no_alternatives() && has_thead_homogeneous_vlenb() < 0) {
878886
pr_warn("Unsupported heterogeneous vlenb detected, vector extension disabled.\n");
879887
disable_xtheadvector();
880888
}

drivers/base/cpu.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ CPU_SHOW_VULN_FALLBACK(retbleed);
599599
CPU_SHOW_VULN_FALLBACK(spec_rstack_overflow);
600600
CPU_SHOW_VULN_FALLBACK(gds);
601601
CPU_SHOW_VULN_FALLBACK(reg_file_data_sampling);
602+
CPU_SHOW_VULN_FALLBACK(ghostwrite);
602603

603604
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
604605
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
@@ -614,6 +615,7 @@ static DEVICE_ATTR(retbleed, 0444, cpu_show_retbleed, NULL);
614615
static DEVICE_ATTR(spec_rstack_overflow, 0444, cpu_show_spec_rstack_overflow, NULL);
615616
static DEVICE_ATTR(gather_data_sampling, 0444, cpu_show_gds, NULL);
616617
static DEVICE_ATTR(reg_file_data_sampling, 0444, cpu_show_reg_file_data_sampling, NULL);
618+
static DEVICE_ATTR(ghostwrite, 0444, cpu_show_ghostwrite, NULL);
617619

618620
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
619621
&dev_attr_meltdown.attr,
@@ -630,6 +632,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
630632
&dev_attr_spec_rstack_overflow.attr,
631633
&dev_attr_gather_data_sampling.attr,
632634
&dev_attr_reg_file_data_sampling.attr,
635+
&dev_attr_ghostwrite.attr,
633636
NULL
634637
};
635638

include/linux/cpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ extern ssize_t cpu_show_gds(struct device *dev,
7777
struct device_attribute *attr, char *buf);
7878
extern ssize_t cpu_show_reg_file_data_sampling(struct device *dev,
7979
struct device_attribute *attr, char *buf);
80+
extern ssize_t cpu_show_ghostwrite(struct device *dev, struct device_attribute *attr, char *buf);
8081

8182
extern __printf(4, 5)
8283
struct device *cpu_device_create(struct device *parent, void *drvdata,

0 commit comments

Comments
 (0)