Skip to content

Commit d25f256

Browse files
Andrew Jonespalmer-dabbelt
authored andcommitted
RISC-V: cpufeatures: Put the upper 16 bits of patch ID to work
cpufeature IDs are consecutive integers starting at 26, so a 32-bit patch ID allows an aircraft carrier load of feature IDs. Repurposing the upper 16 bits still leaves a boat load of feature IDs and gains 16 bits which may be used to control patching on a per patch-site basis. This will be initially used in Zicboz's application to clear_page(), as Zicboz's block size must also be considered. In that case, the upper 16-bit value's role will be to convey the maximum block size which the Zicboz clear_page() implementation supports. cpufeature patch sites which need to check for the existence or absence of other cpufeatures may also be able to make use of this. Signed-off-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Conor Dooley <conor.dooley@microchip.com> Link: https://lore.kernel.org/r/20230224162631.405473-6-ajones@ventanamicro.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent 7ea5a73 commit d25f256

2 files changed

Lines changed: 37 additions & 4 deletions

File tree

arch/riscv/include/asm/alternative.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@
1313
#ifdef CONFIG_RISCV_ALTERNATIVE
1414

1515
#include <linux/init.h>
16+
#include <linux/kernel.h>
1617
#include <linux/types.h>
1718
#include <linux/stddef.h>
1819
#include <asm/hwcap.h>
1920

21+
#define PATCH_ID_CPUFEATURE_ID(p) lower_16_bits(p)
22+
#define PATCH_ID_CPUFEATURE_VALUE(p) upper_16_bits(p)
23+
2024
#define RISCV_ALTERNATIVES_BOOT 0 /* alternatives applied during regular boot */
2125
#define RISCV_ALTERNATIVES_MODULE 1 /* alternatives applied during module-init */
2226
#define RISCV_ALTERNATIVES_EARLY_BOOT 2 /* alternatives applied before mmu start */

arch/riscv/kernel/cpufeature.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,26 +274,55 @@ void __init riscv_fill_hwcap(void)
274274
}
275275

276276
#ifdef CONFIG_RISCV_ALTERNATIVE
277+
/*
278+
* Alternative patch sites consider 48 bits when determining when to patch
279+
* the old instruction sequence with the new. These bits are broken into a
280+
* 16-bit vendor ID and a 32-bit patch ID. A non-zero vendor ID means the
281+
* patch site is for an erratum, identified by the 32-bit patch ID. When
282+
* the vendor ID is zero, the patch site is for a cpufeature. cpufeatures
283+
* further break down patch ID into two 16-bit numbers. The lower 16 bits
284+
* are the cpufeature ID and the upper 16 bits are used for a value specific
285+
* to the cpufeature and patch site. If the upper 16 bits are zero, then it
286+
* implies no specific value is specified. cpufeatures that want to control
287+
* patching on a per-site basis will provide non-zero values and implement
288+
* checks here. The checks return true when patching should be done, and
289+
* false otherwise.
290+
*/
291+
static bool riscv_cpufeature_patch_check(u16 id, u16 value)
292+
{
293+
if (!value)
294+
return true;
295+
296+
return false;
297+
}
298+
277299
void __init_or_module riscv_cpufeature_patch_func(struct alt_entry *begin,
278300
struct alt_entry *end,
279301
unsigned int stage)
280302
{
281303
struct alt_entry *alt;
282304
void *oldptr, *altptr;
305+
u16 id, value;
283306

284307
if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
285308
return;
286309

287310
for (alt = begin; alt < end; alt++) {
288311
if (alt->vendor_id != 0)
289312
continue;
290-
if (alt->patch_id >= RISCV_ISA_EXT_MAX) {
291-
WARN(1, "This extension id:%d is not in ISA extension list",
292-
alt->patch_id);
313+
314+
id = PATCH_ID_CPUFEATURE_ID(alt->patch_id);
315+
316+
if (id >= RISCV_ISA_EXT_MAX) {
317+
WARN(1, "This extension id:%d is not in ISA extension list", id);
293318
continue;
294319
}
295320

296-
if (!__riscv_isa_extension_available(NULL, alt->patch_id))
321+
if (!__riscv_isa_extension_available(NULL, id))
322+
continue;
323+
324+
value = PATCH_ID_CPUFEATURE_VALUE(alt->patch_id);
325+
if (!riscv_cpufeature_patch_check(id, value))
297326
continue;
298327

299328
oldptr = ALT_OLD_PTR(alt);

0 commit comments

Comments
 (0)