File Index
Files and directories
Sign in
FILE

errata.c

File preview with syntax highlighting.

linux-6.19.14/arch/riscv/errata/sifive/errata.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2021 Sifive.
  4 */
  5
  6#include <linux/kernel.h>
  7#include <linux/memory.h>
  8#include <linux/module.h>
  9#include <linux/string.h>
 10#include <linux/bug.h>
 11#include <asm/text-patching.h>
 12#include <asm/alternative.h>
 13#include <asm/vendorid_list.h>
 14#include <asm/errata_list.h>
 15#include <asm/vendor_extensions.h>
 16
 17struct errata_info_t {
 18	char name[32];
 19	bool (*check_func)(unsigned long  arch_id, unsigned long impid);
 20};
 21
 22static bool errata_cip_453_check_func(unsigned long  arch_id, unsigned long impid)
 23{
 24	/*
 25	 * Affected cores:
 26	 * Architecture ID: 0x8000000000000007
 27	 * Implement ID: 0x20181004 <= impid <= 0x20191105
 28	 */
 29	if (arch_id != 0x8000000000000007 ||
 30	    (impid < 0x20181004 || impid > 0x20191105))
 31		return false;
 32	return true;
 33}
 34
 35static bool errata_cip_1200_check_func(unsigned long  arch_id, unsigned long impid)
 36{
 37	/*
 38	 * Affected cores:
 39	 * Architecture ID: 0x8000000000000007 or 0x1
 40	 * Implement ID: mimpid[23:0] <= 0x200630 and mimpid != 0x01200626
 41	 */
 42	if (arch_id != 0x8000000000000007 && arch_id != 0x1)
 43		return false;
 44	if ((impid & 0xffffff) > 0x200630 || impid == 0x1200626)
 45		return false;
 46
 47#ifdef CONFIG_MMU
 48	tlb_flush_all_threshold = 0;
 49#endif
 50
 51	return true;
 52}
 53
 54static struct errata_info_t errata_list[ERRATA_SIFIVE_NUMBER] = {
 55	{
 56		.name = "cip-453",
 57		.check_func = errata_cip_453_check_func
 58	},
 59	{
 60		.name = "cip-1200",
 61		.check_func = errata_cip_1200_check_func
 62	},
 63};
 64
 65static u32 __init_or_module sifive_errata_probe(unsigned long archid,
 66						unsigned long impid)
 67{
 68	int idx;
 69	u32 cpu_req_errata = 0;
 70
 71	for (idx = 0; idx < ERRATA_SIFIVE_NUMBER; idx++)
 72		if (errata_list[idx].check_func(archid, impid))
 73			cpu_req_errata |= (1U << idx);
 74
 75	return cpu_req_errata;
 76}
 77
 78void sifive_errata_patch_func(struct alt_entry *begin, struct alt_entry *end,
 79			      unsigned long archid, unsigned long impid,
 80			      unsigned int stage)
 81{
 82	struct alt_entry *alt;
 83	u32 cpu_req_errata;
 84	u32 tmp;
 85
 86	BUILD_BUG_ON(ERRATA_SIFIVE_NUMBER >= RISCV_VENDOR_EXT_ALTERNATIVES_BASE);
 87
 88	if (stage == RISCV_ALTERNATIVES_EARLY_BOOT)
 89		return;
 90
 91	cpu_req_errata = sifive_errata_probe(archid, impid);
 92
 93	for (alt = begin; alt < end; alt++) {
 94		if (alt->vendor_id != SIFIVE_VENDOR_ID)
 95			continue;
 96		if (alt->patch_id >= ERRATA_SIFIVE_NUMBER) {
 97			WARN(1, "This errata id:%d is not in kernel errata list", alt->patch_id);
 98			continue;
 99		}
100
101		tmp = (1U << alt->patch_id);
102		if (cpu_req_errata & tmp) {
103			mutex_lock(&text_mutex);
104			patch_text_nosync(ALT_OLD_PTR(alt), ALT_ALT_PTR(alt),
105					  alt->alt_len);
106			mutex_unlock(&text_mutex);
107		}
108	}
109}
~/ Read-only file preview.