Skip to content

Commit a9429d5

Browse files
Merge patch series "RISC-V: Enable cbo.zero in usermode"
Andrew Jones <ajones@ventanamicro.com> says: In order for usermode to issue cbo.zero, it needs privilege granted to issue the extension instruction (patch 2) and to know that the extension is available and its block size (patch 3). Patch 1 could be separate from this series (it just fixes up some error messages), patches 4-5 convert the hwprobe selftest to a statically-linked, TAP test and patch 6 adds a new hwprobe test for the new information as well as testing CBO instructions can or cannot be issued as appropriate. * b4-shazam-merge: RISC-V: selftests: Add CBO tests RISC-V: selftests: Convert hwprobe test to kselftest API RISC-V: selftests: Statically link hwprobe test RISC-V: hwprobe: Expose Zicboz extension and its block size RISC-V: Enable cbo.zero in usermode RISC-V: Make zicbom/zicboz errors consistent Link: https://lore.kernel.org/r/20230918131518.56803-8-ajones@ventanamicro.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2 parents 71e11d0 + a29e2a4 commit a9429d5

File tree

14 files changed

+345
-63
lines changed

14 files changed

+345
-63
lines changed

Documentation/riscv/hwprobe.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ The following keys are defined:
7777
* :c:macro:`RISCV_HWPROBE_EXT_ZBS`: The Zbs extension is supported, as defined
7878
in version 1.0 of the Bit-Manipulation ISA extensions.
7979

80+
* :c:macro:`RISCV_HWPROBE_EXT_ZICBOZ`: The Zicboz extension is supported, as
81+
ratified in commit 3dd606f ("Create cmobase-v1.0.pdf") of riscv-CMOs.
82+
8083
* :c:macro:`RISCV_HWPROBE_KEY_CPUPERF_0`: A bitmask that contains performance
8184
information about the selected set of processors.
8285

@@ -96,3 +99,6 @@ The following keys are defined:
9699

97100
* :c:macro:`RISCV_HWPROBE_MISALIGNED_UNSUPPORTED`: Misaligned accesses are
98101
not supported at all and will generate a misaligned address fault.
102+
103+
* :c:macro:`RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE`: An unsigned int which
104+
represents the size of the Zicboz block in bytes.

arch/riscv/include/asm/cpufeature.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@ DECLARE_PER_CPU(long, misaligned_access_speed);
3131
extern struct riscv_isainfo hart_isa[NR_CPUS];
3232

3333
void check_unaligned_access(int cpu);
34+
void riscv_user_isa_enable(void);
3435

3536
#endif

arch/riscv/include/asm/csr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@
275275
#define CSR_SIE 0x104
276276
#define CSR_STVEC 0x105
277277
#define CSR_SCOUNTEREN 0x106
278+
#define CSR_SENVCFG 0x10a
278279
#define CSR_SSCRATCH 0x140
279280
#define CSR_SEPC 0x141
280281
#define CSR_SCAUSE 0x142

arch/riscv/include/asm/hwcap.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
#ifndef __ASSEMBLY__
7171

7272
#include <linux/jump_label.h>
73+
#include <asm/cpufeature.h>
7374

7475
unsigned long riscv_get_elf_hwcap(void);
7576

@@ -137,6 +138,21 @@ riscv_has_extension_unlikely(const unsigned long ext)
137138
return true;
138139
}
139140

141+
static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext)
142+
{
143+
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_likely(ext))
144+
return true;
145+
146+
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
147+
}
148+
149+
static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsigned long ext)
150+
{
151+
if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_unlikely(ext))
152+
return true;
153+
154+
return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
155+
}
140156
#endif
141157

142158
#endif /* _ASM_RISCV_HWCAP_H */

arch/riscv/include/asm/hwprobe.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88

99
#include <uapi/asm/hwprobe.h>
1010

11-
#define RISCV_HWPROBE_MAX_KEY 5
11+
#define RISCV_HWPROBE_MAX_KEY 6
1212

1313
#endif

arch/riscv/include/uapi/asm/hwprobe.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@ struct riscv_hwprobe {
2929
#define RISCV_HWPROBE_EXT_ZBA (1 << 3)
3030
#define RISCV_HWPROBE_EXT_ZBB (1 << 4)
3131
#define RISCV_HWPROBE_EXT_ZBS (1 << 5)
32+
#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6)
3233
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
3334
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
3435
#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
3536
#define RISCV_HWPROBE_MISALIGNED_SLOW (2 << 0)
3637
#define RISCV_HWPROBE_MISALIGNED_FAST (3 << 0)
3738
#define RISCV_HWPROBE_MISALIGNED_UNSUPPORTED (4 << 0)
3839
#define RISCV_HWPROBE_MISALIGNED_MASK (7 << 0)
40+
#define RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE 6
3941
/* Increase RISCV_HWPROBE_MAX_KEY when adding items. */
4042

4143
#endif

arch/riscv/kernel/cpufeature.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,10 @@ static bool riscv_isa_extension_check(int id)
9393
return true;
9494
case RISCV_ISA_EXT_ZICBOZ:
9595
if (!riscv_cboz_block_size) {
96-
pr_err("Zicboz detected in ISA string, but no cboz-block-size found\n");
96+
pr_err("Zicboz detected in ISA string, disabling as no cboz-block-size found\n");
9797
return false;
9898
} else if (!is_power_of_2(riscv_cboz_block_size)) {
99-
pr_err("cboz-block-size present, but is not a power-of-2\n");
99+
pr_err("Zicboz disabled as cboz-block-size present, but is not a power-of-2\n");
100100
return false;
101101
}
102102
return true;
@@ -653,6 +653,12 @@ static int check_unaligned_access_boot_cpu(void)
653653

654654
arch_initcall(check_unaligned_access_boot_cpu);
655655

656+
void riscv_user_isa_enable(void)
657+
{
658+
if (riscv_cpu_has_extension_unlikely(smp_processor_id(), RISCV_ISA_EXT_ZICBOZ))
659+
csr_set(CSR_SENVCFG, ENVCFG_CBZE);
660+
}
661+
656662
#ifdef CONFIG_RISCV_ALTERNATIVE
657663
/*
658664
* Alternative patch sites consider 48 bits when determining when to patch

arch/riscv/kernel/setup.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <asm/acpi.h>
2727
#include <asm/alternative.h>
2828
#include <asm/cacheflush.h>
29+
#include <asm/cpufeature.h>
2930
#include <asm/cpu_ops.h>
3031
#include <asm/early_ioremap.h>
3132
#include <asm/pgtable.h>
@@ -314,10 +315,13 @@ void __init setup_arch(char **cmdline_p)
314315
riscv_fill_hwcap();
315316
init_rt_signal_env();
316317
apply_boot_alternatives();
318+
317319
if (IS_ENABLED(CONFIG_RISCV_ISA_ZICBOM) &&
318320
riscv_isa_extension_available(NULL, ZICBOM))
319321
riscv_noncoherent_supported();
320322
riscv_set_dma_cache_alignment();
323+
324+
riscv_user_isa_enable();
321325
}
322326

323327
static int __init topology_init(void)

arch/riscv/kernel/smpboot.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include <linux/of.h>
2626
#include <linux/sched/task_stack.h>
2727
#include <linux/sched/mm.h>
28+
29+
#include <asm/cpufeature.h>
2830
#include <asm/cpu_ops.h>
2931
#include <asm/cpufeature.h>
3032
#include <asm/irq.h>
@@ -253,6 +255,8 @@ asmlinkage __visible void smp_callin(void)
253255
elf_hwcap &= ~COMPAT_HWCAP_ISA_V;
254256
}
255257

258+
riscv_user_isa_enable();
259+
256260
/*
257261
* Remote TLB flushes are ignored while the CPU is offline, so emit
258262
* a local TLB flush right now just in case.

arch/riscv/kernel/sys_riscv.c

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -145,26 +145,38 @@ static void hwprobe_isa_ext0(struct riscv_hwprobe *pair,
145145
for_each_cpu(cpu, cpus) {
146146
struct riscv_isainfo *isainfo = &hart_isa[cpu];
147147

148-
if (riscv_isa_extension_available(isainfo->isa, ZBA))
149-
pair->value |= RISCV_HWPROBE_EXT_ZBA;
150-
else
151-
missing |= RISCV_HWPROBE_EXT_ZBA;
152-
153-
if (riscv_isa_extension_available(isainfo->isa, ZBB))
154-
pair->value |= RISCV_HWPROBE_EXT_ZBB;
155-
else
156-
missing |= RISCV_HWPROBE_EXT_ZBB;
157-
158-
if (riscv_isa_extension_available(isainfo->isa, ZBS))
159-
pair->value |= RISCV_HWPROBE_EXT_ZBS;
160-
else
161-
missing |= RISCV_HWPROBE_EXT_ZBS;
148+
#define EXT_KEY(ext) \
149+
do { \
150+
if (__riscv_isa_extension_available(isainfo->isa, RISCV_ISA_EXT_##ext)) \
151+
pair->value |= RISCV_HWPROBE_EXT_##ext; \
152+
else \
153+
missing |= RISCV_HWPROBE_EXT_##ext; \
154+
} while (false)
155+
156+
/*
157+
* Only use EXT_KEY() for extensions which can be exposed to userspace,
158+
* regardless of the kernel's configuration, as no other checks, besides
159+
* presence in the hart_isa bitmap, are made.
160+
*/
161+
EXT_KEY(ZBA);
162+
EXT_KEY(ZBB);
163+
EXT_KEY(ZBS);
164+
EXT_KEY(ZICBOZ);
165+
#undef EXT_KEY
162166
}
163167

164168
/* Now turn off reporting features if any CPU is missing it. */
165169
pair->value &= ~missing;
166170
}
167171

172+
static bool hwprobe_ext0_has(const struct cpumask *cpus, unsigned long ext)
173+
{
174+
struct riscv_hwprobe pair;
175+
176+
hwprobe_isa_ext0(&pair, cpus);
177+
return (pair.value & ext);
178+
}
179+
168180
static u64 hwprobe_misaligned(const struct cpumask *cpus)
169181
{
170182
int cpu;
@@ -215,6 +227,12 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
215227
pair->value = hwprobe_misaligned(cpus);
216228
break;
217229

230+
case RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE:
231+
pair->value = 0;
232+
if (hwprobe_ext0_has(cpus, RISCV_HWPROBE_EXT_ZICBOZ))
233+
pair->value = riscv_cboz_block_size;
234+
break;
235+
218236
/*
219237
* For forward compatibility, unknown keys don't fail the whole
220238
* call, but get their element key set to -1 and value set to 0

0 commit comments

Comments
 (0)